windows 批处理文件:列出具有相对路径的目录中的所有文件

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/8385454/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-09-09 08:59:12  来源:igfitidea点击:

Batch files: List all files in a directory with relative paths

windowsbatch-filecmd

提问by Tim Meyer

Concerning Windows batch files: Is there a way to list all the files (or all of a specific type) in a certain directory and its subdirectories, including the paths relative to the current (or the search) directory in the list?

关于 Windows 批处理文件:有没有办法列出某个目录及其子目录中的所有文件(或所有特定类型),包括相对于列表中当前(或搜索)目录的路径?

For example, if I want all the .txt files in the current directory and subdirectories with their full paths, I can do

例如,如果我想要当前目录和子目录中的所有 .txt 文件及其完整路径,我可以这样做

for /r . %%g in (*.txt) do echo %%g >> C:\temp\test.txt

or

或者

dir *.txt /b /s >> C:\temp\test.txt

and I will get something like

我会得到类似的东西

C:\test\Doc1.txt
C:\test\subdir\Doc2.txt
C:\test\subdir\Doc3.txt

If I do

如果我做

for /r . %%g in (*.txt) do echo %%~nxg >> C:\temp\test.txt

I will get something like

我会得到类似的东西

Doc1.txt
Doc2.txt
Doc3.txt

But what I really want is:

但我真正想要的是:

Doc1.txt
subdir\Doc2.txt
subdir\Doc3.txt

Is it possible?

是否可以?

If my post is too confusing: I basically want List files recursively in Linux CLI with path relative to the current directory, but just for Windows.

如果我的帖子太混乱:我基本上希望在 Linux CLI 中递归列出文件,路径相对于当前目录,但仅适用于 Windows。

采纳答案by jeb

You could simply get the character length of the current directory, and remove them from your absolute list

您可以简单地获取当前目录的字符长度,并将它们从绝对列表中删除

setlocal EnableDelayedExpansion
for /L %%n in (1 1 500) do if "!__cd__:~%%n,1!" neq "" set /a "len=%%n+1"
setlocal DisableDelayedExpansion
for /r . %%g in (*.log) do (
  set "absPath=%%g"
  setlocal EnableDelayedExpansion
  set "relPath=!absPath:~%len%!"
  echo(!relPath!
  endlocal
)

回答by dbenham

The simplest (but not the fastest) way to iterate a directory tree and list relative file paths is to use FORFILES.

迭代目录树并列出相对文件路径的最简单(但不是最快)的方法是使用FORFILES

forfiles /s /m *.txt /c "cmd /c echo @relpath"

The relative paths will be quoted with a leading .\as in

相对路径将用前导引用,.\

".\Doc1.txt"
".\subdir\Doc2.txt"
".\subdir\Doc3.txt"


To remove quotes:


要删除引号:

for /f %%A in ('forfiles /s /m *.txt /c "cmd /c echo @relpath"') do echo %%~A


To remove quotes and the leading .\:


删除引号和前导.\

setlocal disableDelayedExpansion
for /f "delims=" %%A in ('forfiles /s /m *.txt /c "cmd /c echo @relpath"') do (
  set "file=%%~A"
  setlocal enableDelayedExpansion
  echo !file:~2!
  endlocal
)

or without using delayed expansion

或不使用延迟扩展

for /f "tokens=1* delims=\" %%A in (
  'forfiles /s /m *.txt /c "cmd /c echo @relpath"'
) do for %%F in (^"%%B) do echo %%~F

回答by Andriy M

This answer will not work correctly with root paths containing equal signs (=). (Thanks @dbenham for pointing that out.)

此答案不适用于包含等号 ( =) 的根路径。(感谢@dbenham 指出这一点。)



EDITED:Fixed the issue with paths containing !, again spotted by @dbenham (thanks!).

编辑:修复了路径包含的问题!,再次被@dbenham 发现(谢谢!)。

Alternatively to calculating the length and extracting substrings you could use a different approach:

作为计算长度和提取子字符串的替代方法,您可以使用不同的方法:

  • store the root path;

  • clear the root path from the file paths.

  • 存储根路径;

  • 从文件路径中清除根路径。

Here's my attempt (which worked for me):

这是我的尝试(对我有用):

@ECHO OFF
SETLOCAL DisableDelayedExpansion
SET "r=%__CD__%"
FOR /R . %%F IN (*) DO (
  SET "p=%%F"
  SETLOCAL EnableDelayedExpansion
  ECHO(!p:%r%=!
  ENDLOCAL
)

The rvariable is assigned with the current directory. Unless the current directory is the root directory of a disk drive, it will not end with \, which we amend by appending the character.(No longer the case, as the script now reads the __CD__variable, whose value always ends with \(thanks @jeb!), instead of CD.)

r变量分配与当前目录。除非当前目录是磁盘驱动器的根目录,否则它不会以 结尾\,我们通过附加字符来修改它。(情况不再如此,因为脚本现在读取 __CD__变量,其值总是以\(感谢@jeb!)结尾,而不是CD。)

In the loop, we store the current file path into a variable. Then we output the variable, stripping the root path along the way.

在循环中,我们将当前文件路径存储到一个变量中。然后我们输出变量,沿途剥离根路径。

回答by Aacini

Of course, you may write a recursive algorithm in Batch that gives you exact control of what you do in every nested subdirectory:

当然,您可以在 Batch 中编写递归算法,让您精确控制在每个嵌套子目录中的操作:

@echo off
set mypath=
call :treeProcess
goto :eof

:treeProcess
setlocal
for %%f in (*.txt) do echo %mypath%%%f
for /D %%d in (*) do (
    set mypath=%mypath%%%d\
    cd %%d
    call :treeProcess
    cd ..
)
endlocal
exit /b

回答by Kedar

@echo on>out.txt
@echo off
setlocal enabledelayedexpansion
set "parentfolder=%CD%"
for /r . %%g in (*.*) do (
  set "var=%%g"
  set var=!var:%parentfolder%=!
  echo !var! >> out.txt
)