使用“for”循环迭代目录中的所有文件

446

如何使用 for 循环遍历目录中的每个文件?

如何判断某个条目是一个目录还是一个文件?


1
假设您指的是默认的Windows shell,我已经重新标记了您的帖子以获得更清晰的说明。 - David Schmitt
2
请同时指明您使用的Windows版本。 - jop
1
这应该分成两个独立的问题,因为它们彼此独立。 - julealgon
17个回答

611

此命令递归地列出当前目录及其子目录中的所有文件(仅限文件):

for /r %i in (*) do echo %i

如果在批处理文件中运行该命令,则需要将%符号加倍。

for /r %%i in (*) do echo %%i

(感谢@agnul)


95
如若您不想递归使用此命令,请确保删除 /r。 - jocull
37
如果您想在当前目录(递归地)仅回显带有其扩展名的文件名(而不是完整路径),可以像这样执行操作:for /r %i in (*) do ( echo %~nxi )。这个线程也非常有用:https://dev59.com/X3VD5IYBdhLWcg3wBm5h。 - Sk8erPeter
2
@Vaccano 是的,在 Do 后面使用括号。例如,do (echo %i&del %i)。您还可以使用“enter”而不是“&”来执行多个命令。 - Jay
4
如果您正在使用类似于复制/移动之类的命令而不是echo,请确保正确引用路径。对于每个文件,使用for /r %%i in (*) do echo "%%i"。 - Soundararajan
2
你似乎需要使用单个字母的变量名。 - Álvaro González
显示剩余3条评论

258

遍历...

  • ...当前目录下的文件:for %f in (.\*) do @echo %f
  • ...当前目录下的子目录:for /D %s in (.\*) do @echo %s
  • ...当前目录及其所有子目录下的文件:for /R %f in (.\*) do @echo %f
  • ...当前目录及其所有子目录下的子目录:for /R /D %s in (.\*) do @echo %s

不幸的是,我没有找到一种同时遍历文件和子目录的方法。

只需使用cygwin以获取更多功能的bash。

除此之外:您是否注意到MS Windows内置帮助是cmd命令行语法描述的好资源?

还可以在此处查看:http://technet.microsoft.com/en-us/library/bb490890.aspx


25
"%file"和"%subdir"只能为一个字符,比如"%f"、"%s"。 - Felix Dombek
1
“当前目录中的子目录”不起作用。我收到了一个错误:s在此时是意外的。 - Gabriel
for /R /D %s in (.\*) do @echo %s 对我不起作用,它在所有路径中都添加了额外的\.。我能够使用 (*) 仅处理子目录,但我找不到一种方法来在子目录和当前目录中执行 FOR...DO。 - Micah Lindstrom

129

要遍历每个文件,可以使用 for 循环:

for %%f in (directory\path\*) do ( something_here )

在我的情况下,我还想获取文件内容、名称等信息。

这导致了一些问题,我认为我的用例可能会有所帮助。以下是一个循环,它从目录中的每个“.txt”文件中读取信息,并允许您执行某些操作(例如设置 setx)。

@ECHO OFF
setlocal enabledelayedexpansion
for %%f in (directory\path\*.txt) do (
  set /p val=<%%f
  echo "fullname: %%f"
  echo "name: %%~nf"
  echo "contents: !val!"
)

*限制:val<=%%f只会获取文件的第一行。


35
啊,多行示例。谢谢! - Nyerguds
@Aaron Votre 怎样结束一个循环? - nijogeorgep
1
@nijogeorgep 不需要“结束”循环。在我的示例中,括号内的所有内容(echo等)将对目录中的每个‘*.txt’文件运行一次。我认为你要寻找的答案可能在这里更好地解释:https://dev59.com/x3M_5IYBdhLWcg3wfTO7 - Aaron Votre
@Aaron Votre 我试图使用脚本运行一些maven命令,但它一直在无限循环,所以我请求帮助。现在我已经添加了一个退出循环的语句并解决了我的问题。 - nijogeorgep
@nijogeorgep 很高兴你解决了问题! - Aaron Votre

67

在从命令行和批处理文件运行 FOR 命令之间存在微妙的差异。在批处理文件中,需要在每个变量引用前面放置两个 % 字符。

从命令行运行:

FOR %i IN (*) DO ECHO %i

从批处理文件:

FOR %%i IN (*) DO ECHO %%i

45

这个 for 循环将列出目录中的所有文件。

pushd somedir
for /f "delims=" %%f in ('dir /b /a-d-h-s') do echo %%f
popd

"delims=" 选项很有用,可以显示文件名含有空格的长文件名。

"/b" 选项仅显示名称,而不包括大小、日期等信息。

有关 dir 命令中 "/a" 选项的一些要点:

  • 任何使用 "/a" 的情况都会列出所有内容,包括隐藏和系统属性。
  • "/ad" 只会显示子目录,包括隐藏和系统子目录。
  • "/a-d" 参数会排除具有 'D'irectory 属性的内容。
  • "/a-d-h-s" 会显示所有内容,但不包括带有 'D'irectory,'H'idden 或 'S'ystem 属性的条目。

如果在命令行上使用此命令,请删除一个 "%" 符号。

希望这能帮到您。


14

%1指的是传入的第一个参数,在迭代器中不可用。

尝试这样做:

@echo off
for %%i in (*.*) do echo %%i

你说得对。我在立即模式下尝试检查FOR语法,并将该行直接粘贴到答案中,忘记了参数 :-) - Axeman

11

我在使用绝对路径时遇到了麻烦,直到我找到这个参考:https://ss64.com/nt/for_r.html

以下示例循环遍历由绝对路径给出的目录中的所有文件。

For /R C:\absoulte\path\ %%G IN (*.*) do (
  Echo %%G
)

如果你想要 解构%%G来获取路径、名称、扩展名... - Mr. Polywhirl

10

要遍历所有文件和文件夹,您可以使用

for /F "delims=" %%a in ('dir /b /s') do echo %%a

如果您只想遍历所有文件夹而不是文件,则可以使用:

for /F "delims=" %%a in ('dir /a:d /b /s') do echo %%a

如果你想在整个目录树中获取所有结果,可以使用/s。如果你只想遍历该文件夹的内容而不是其子文件夹,可以忽略/s

在迭代中实现搜索

要遍历特定命名的文件和文件夹,可以搜索名称并使用for循环进行迭代。

for /F "delims=" %%a in ('dir "file or folder name" /b /s') do echo %%a

要遍历特定的文件夹/目录而不是文件,可以在同一命令中使用/AD

for /F "delims=" %%a in ('dir "folder name" /b /AD /s') do echo %%a

太棒了!如果要搜索的文件夹名称中包含空格字符,只有您的方法有效!例如:for /F "delims=" %%a in ('dir "My Folder1", "My Folder2" /b /AD /s') do ...,从这里可以找到一些注意事项:IN()子句被单引号括起来意味着FOR /F将内容视为命令,并逐行处理命令的输出。"delims="选项意味着不解析成标记(保留每一行的完整内容)。因此,每一行都会被迭代加载到%%a变量中。 - S.Serpooshan
我在尝试排除.git目录时遇到了一个错误,就像这样. . . for /F "delims=" %%f in ('dir /b /s | find /i /v ".git"') do . . . - undefined
我找到了答案。我需要逃避管道命令... for /F "delims=" %%f in ('dir /b /s ^| find /i /v ".git"') do... - undefined

9

这是我带有代码注释的尝试。

我只是在梳理我的技能,如有任何明显的错误请谅解。

我尽力写出一个全功能的解决方案,并在需要时进行了一些小修改。

一些重要说明:如果您只想处理根目录下的文件和文件夹,请将变量recursive更改为FALSE。否则,它会遍历所有文件夹和文件。

欢迎提出意见...

@echo off
title %~nx0
chcp 65001 >NUL
set "dir=c:\users\%username%\desktop"
::
:: Recursive Loop routine - First Written by Ste on - 2020.01.24 - Rev 1
::
setlocal EnableDelayedExpansion
rem THIS IS A RECURSIVE SOLUTION [ALBEIT IF YOU CHANGE THE RECURSIVE TO FALSE, NO]
rem By removing the /s switch from the first loop if you want to loop through
rem the base folder only.
set recursive=TRUE
if %recursive% equ TRUE ( set recursive=/s ) else ( set recursive= )
endlocal & set recursive=%recursive%
cd /d %dir%
echo Directory %cd%
for %%F in ("*") do (echo    → %%F)                                 %= Loop through the current directory. =%
for /f "delims==" %%D in ('dir "%dir%" /ad /b %recursive%') do (    %= Loop through the sub-directories only if the recursive variable is TRUE. =%
  echo Directory %%D
  echo %recursive% | find "/s" >NUL 2>NUL && (
    pushd %%D
    cd /d %%D
    for /f "delims==" %%F in ('dir "*" /b') do (                      %= Then loop through each pushd' folder and work on the files and folders =%
      echo %%~aF | find /v "d" >NUL 2>NUL && (                        %= This will weed out the directories by checking their attributes for the lack of 'd' with the /v switch therefore you can now work on the files only. =%
      rem You can do stuff to your files here.
      rem Below are some examples of the info you can get by expanding the %%F variable.
      rem Uncomment one at a time to see the results.
      echo    → %%~F           &rem expands %%F removing any surrounding quotes (")
      rem echo    → %%~dF          &rem expands %%F to a drive letter only
      rem echo    → %%~fF          &rem expands %%F to a fully qualified path name
      rem echo    → %%~pF          &rem expands %%A to a path only
      rem echo    → %%~nF          &rem expands %%F to a file name only
      rem echo    → %%~xF          &rem expands %%F to a file extension only
      rem echo    → %%~sF          &rem expanded path contains short names only
      rem echo    → %%~aF          &rem expands %%F to file attributes of file
      rem echo    → %%~tF          &rem expands %%F to date/time of file
      rem echo    → %%~zF          &rem expands %%F to size of file
      rem echo    → %%~dpF         &rem expands %%F to a drive letter and path only
      rem echo    → %%~nxF         &rem expands %%F to a file name and extension only
      rem echo    → %%~fsF         &rem expands %%F to a full path name with short names only
      rem echo    → %%~dp$dir:F    &rem searches the directories listed in the 'dir' environment variable and expands %%F to the fully qualified name of the first one found. If the environment variable name is not defined or the file is not found by the search, then this modifier expands to the empty string
      rem echo    → %%~ftzaF       &rem expands %%F to a DIR like output line
      )
      )
    popd
    )
  )
echo/ & pause & cls

5
for %1 in (*.*) do echo %1

在cmd中尝试使用"HELP FOR"获得完整指南。

这是XP命令的指南。 http://www.ss64.com/nt/


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接