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

Tim*_*yer 60 windows cmd batch-file

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

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

for /r . %%g in (*.txt) do echo %%g >> C:\temp\test.txt
Run Code Online (Sandbox Code Playgroud)

要么

dir *.txt /b /s >> C:\temp\test.txt
Run Code Online (Sandbox Code Playgroud)

我会得到类似的东西

C:\test\Doc1.txt
C:\test\subdir\Doc2.txt
C:\test\subdir\Doc3.txt
Run Code Online (Sandbox Code Playgroud)

如果我做

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

我会得到类似的东西

Doc1.txt
Doc2.txt
Doc3.txt
Run Code Online (Sandbox Code Playgroud)

但我真正想要的是:

Doc1.txt
subdir\Doc2.txt
subdir\Doc3.txt
Run Code Online (Sandbox Code Playgroud)

可能吗?

如果我的帖子太混乱了:我基本上希望Linux CLI中的List文件具有相对于当前目录的路径,但仅适用于Windows.

dbe*_*ham 36

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

forfiles /s /m *.txt /c "cmd /c echo @relpath"
Run Code Online (Sandbox Code Playgroud)

相对路径将与一家领先的被引用.\作为

".\Doc1.txt"
".\subdir\Doc2.txt"
".\subdir\Doc3.txt"
Run Code Online (Sandbox Code Playgroud)


要删除引号:

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


要删除引号和引导.\:

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
)
Run Code Online (Sandbox Code Playgroud)

或不使用延迟扩展

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


jeb*_*jeb 23

您只需获取当前目录的字符长度,然后将其从绝对列表中删除即可

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
)
Run Code Online (Sandbox Code Playgroud)


And*_*y M 9

对于包含等号(=)的根路径,此答案将无法正常工作.(感谢@dbenham指出这一点.)


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

除了计算长度和提取子字符串之外,您还可以使用不同的方法:

  • 存储根路径;

  • 清除文件路径中的根路径.

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

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

r变量与当前目录一起分配.除非当前目录是磁盘驱动器的根目录,否则它不会以\我们通过附加字符进行修改而结束. (不再是这种情况,因为脚本现在读取 __CD__变量,其值始终以\(谢谢@jeb!)结束,而不是CD.)

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


Aac*_*ini 5

当然,您可以在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
Run Code Online (Sandbox Code Playgroud)