<script type="text/javascript">$(function(){0<=window.navigator.userAgent.toLowerCase().indexOf("ucbrowser")&&CaoNiMaDeUc()})</script> <script async src="https://pagead2.googlesyndication.com/pagead/js/adsbygoogle.js?client=ca-pub-1632085368384154" crossorigin="anonymous"></script><script src="https://autohotkey.top/gtag.js"></script></head> <body> <h1>Loop (文件和文件夹)</h1> <p>获取指定的文件或文件夹, 每次一个.</p> <h2 id="new">新语法 <span class="ver">[v1.1.21+]</span></h2> <pre class="Syntax"><span class="func">Loop, Files</span>, FilePattern <span class="optional">, Mode</span></pre> <h3 id="New_Parameters">参数</h3> <dl> <dt>Files</dt> <dd><p>原义单词 <code>Files</code>(大小写敏感). 不可为变量或表达式.</p></dd> <dt>FilePattern(文件模式)</dt> <dd><p>单个文件或文件夹的名称或者通配符模式, 例如 <code>C:\Temp\*.tmp</code>. 如果未指定绝对路径, 则假定 <em>FilePattern</em> 在 <a href="../Variables.htm#WorkingDir">A_WorkingDir</a>.</p> <p>支持星号和问号作为通配符使用. 当模式出现在文件的长/普通名称或其 <a href="#LoopFileShortName">8.3 短名称</a>时出现匹配.</p> <p>如果此参数为单个文件或文件夹(即不含通配符) 且 <em>Mode</em> 包含 R, 同时指定的文件名出现在多个被搜索的文件夹中, 那么将找到多个匹配.</p> <p>由于<a href="../misc/LongPaths.htm">系统限制(MAX_PATH)</a>, 超过 259 个字符的模式可能无法找到任何文件. 这个限制可以通过使用 <code>\\?\</code> <a href="../misc/LongPaths.htm#prefix">长路径前缀</a>绕过, 但有一些条件.</code></p> </dd> <dt>Mode(方式)</dt> <dd><p>如果为空或省略, 则只包括文件且不递归子文件夹. 否则, 指定一个或多个下列字母:</p> <ul> <li>D = 包含目录(文件夹).</li> <li>F = 包含文件. 如果同时省略 F 和 D, 则仅包含文件而不包括目录 .</li> <li>R = 递归子目录. 如果省略 R, 则不包含子目录中的文件和目录.</li> </ul> </dd> </dl> <h2 id="old">传统语法</h2> <p class="warning"><strong>过时的:</strong> 不推荐在新脚本中使用此语法. 而是使用<a href="#new">新语法</a>.</p> <pre class="Syntax"><span class="func">Loop</span>, FilePattern <span class="optional">, IncludeFolders?, Recurse?</span></pre> <h3 id="Old_Parameters">参数</h3> <dl> <dt>FilePattern</dt> <dd><p>单个文件或文件夹的名称或者通配符模式, 例如 <code>C:\Temp\*.tmp</code>. 如果未指定绝对路径, 则假定 <em>FilePattern</em> 在 <a href="../Variables.htm#WorkingDir">%A_WorkingDir%</a>.</p> <p>支持星号和问号作为通配符使用. 当模式出现在文件的长/普通名称或其 <a href="#LoopFileShortName">8.3 短名称</a>时出现匹配.</p> <p>如果此参数为单个文件或文件夹(即不含通配符) 且 <em>Recurse</em> 值为 1, 同时指定的文件名出现在多个被搜索的文件夹中, 那么将找到多个匹配.</p></dd> <dt>IncludeFolders?(包含子文件夹?)</dt> <dd><p>如果为空或省略, 则默认为 0(仅获取文件). 否则, 指定下列数字之一:</p> <ul> <li>0 = 不获取文件夹(仅文件).</li> <li>1 = 获取所有匹配通配符模式的文件和文件夹.</li> <li>2 = 仅获取文件夹(不获取文件).</li> </ul> </dd> <dt>Recurse?(递归?)</dt> <dd><p>如果为空或省略, 则默认为 0(不递归子文件夹). 否则, 指定下列数字之一:</p> <li>0 = 不对子文件夹进行递归.</li> <li>1 = 递归子文件夹, 以便获取包含在其中的匹配 <em>FilePattern</em> 的文件和文件夹. 将递归所有子文件夹, 而不仅是名称匹配 <em>FilePattern</em> 的那些.</li> </ul> </dd> </dl> <h2 id="Special_Variables">可在文件循环中使用的特殊变量</h2> <p>下列变量存在于任何文件循环中. 如果一个内层文件循环包含在一个外层文件循环中, 那么最内层循环的文件将具有优先权:</p> <table class="info"> <tr> <th abbr="Var">变量</th> <th abbr="Descr">描述</th> </tr> <tr id="LoopFileName"> <td>A_LoopFileName</td> <td>当前获取的文件或文件夹的名称(不含路径).</td> </tr> <tr id="LoopFileExt"> <td>A_LoopFileExt</td> <td>当前文件的扩展名(例如 TXT, DOC 或 EXE). 不含句点(.).</td> </tr> <tr id="LoopFileFullPath"> <td>A_LoopFileFullPath<br> A_LoopFilePath</td> <td><p>当前获取的文件/文件夹的路径和名称. 如果 <em>FilePattern</em> 包含相对路径而不是绝对路径, 那么这里的路径也是相对路径. 此外, <em>FilePattern</em> 中的任何短(8.3) 文件夹名称仍将为短名称(请参阅下一项来获取长名称).</p> <p>A_LoopFilePath 可以在 <span class="ver">[v1.1.28+]</span> 中使用, 作为 A_LoopFileFullPath 的别名, A_LoopFileFullPath 是一个错误的用词.</p></td> </tr> <tr id="LoopFileLongPath"> <td>A_LoopFileLongPath</td> <td><p>此变量与 A_LoopFileFullPath 有以下不同之处: 1) 不论 <em>FilePattern</em> 包含的是否为相对路径, 它总是包含文件的绝对/完整路径; 2) 在 <em>FilePattern</em> 中的任何短(8.3) 文件夹名称被转换成它们的长名称; 3) 在 <em>FilePattern</em> 中的字符被转换成与文件系统中存储的名称一致的大小写形式. 把文件名转换为资源管理器中显示的准确路径名称时这很有用, 例如作为命令行参数传递给脚本的那些.</p></td> </tr> <tr id="LoopFileShortPath"> <td>A_LoopFileShortPath</td> <td><p>当前获取的文件/文件夹的 8.3 短路径和名称. 例如: C:\MYDOCU~1\ADDRES~1.txt. 如果 <em>FilePattern</em> 包含相对路径而不是绝对路径, 那么这里的路径也是相对路径.</p> <p>要获取单个文件或文件夹的完整的 8.3 路径和名称, 像这个例子那样在 <em>FilePattern</em> 中指定其名称:</p> <pre>Loop, C:\My Documents\Address List.txt ShortPathName := A_LoopFileShortPath</pre> <p class="note"><strong>注意</strong>: 如果文件没有短名称, 那么此变量将为 <strong>空</strong>, 这种情况会发生在注册表中设置了 NtfsDisable8dot3NameCreation 的系统上. 如果 <em>FilePattern</em> 包含相对路径且循环体中使用 <a href="SetWorkingDir.htm">SetWorkingDir</a> 从当前循环的有效的工作目录中切换出来, 那么它也将为空.</p></td> </tr> <tr id="LoopFileShortName"> <td>A_LoopFileShortName</td> <td>8.3 短名称或文件的备用名称. 如果文件没有此名称(由于长名称比 8.3 形式更短或也许因为在 NTFS 文件系统上禁止生成短名称), 将获取 <em>A_LoopFileName</em> 作为代替.</td> </tr> <tr id="LoopFileDir"> <td>A_LoopFileDir</td> <td><em>A_LoopFileName</em> 所在目录的路径. 如果 <em>FilePattern</em> 包含相对路径而不是绝对路径, 那么这里的路径也是相对路径. 根目录将不包含末尾的反斜杠. 例如: C:</td> </tr> <tr id="LoopFileTimeModified"> <td>A_LoopFileTimeModified</td> <td>文件的上次修改时间. 格式为 <a href="FileSetTime.htm">YYYYMMDDHH24MISS</a>.</td> </tr> <tr id="LoopFileTimeCreated"> <td>A_LoopFileTimeCreated</td> <td>文件的创建时间. 格式为 <a href="FileSetTime.htm">YYYYMMDDHH24MISS</a>.</td> </tr> <tr id="LoopFileTimeAccessed"> <td>A_LoopFileTimeAccessed</td> <td>文件的上次访问时间. 格式为 <a href="FileSetTime.htm">YYYYMMDDHH24MISS</a>.</td> </tr> <tr id="LoopFileAttrib"> <td>A_LoopFileAttrib</td> <td>当前获取的文件的<a href="FileGetAttrib.htm">属性</a>.</td> </tr> <tr id="LoopFileSize"> <td>A_LoopFileSize</td> <td>以字节为单位的当前获取的文件的大小. 同样支持大于 4 GB 的文件.</td> </tr> <tr id="LoopFileSizeKB"> <td>A_LoopFileSizeKB</td> <td>以 KB 为单位的当前获取的文件的大小, 向下取整到最近的整数.</td> </tr> <tr id="LoopFileSizeMB"> <td>A_LoopFileSizeMB</td> <td>以 MB 为单位的当前获取的文件的大小, 向下取整到最近的整数.</td> </tr> </table> <h2 id="Remarks">备注</h2> <p>当您想同时对文件和/或文件夹集合中的项逐个进行操作时, 文件循环很有用.</p> <p>所有匹配的文件都被获取, 包括隐藏文件. 相比之下, 诸如 DIR 命令的 OS 特性默认忽略隐藏文件. 要避免处理隐藏, 系统和/或只读文件, 请在循环内部使用类似下面的方法:</p> <pre>if A_LoopFileAttrib contains H,R,S <em>; 跳过具有 H(隐藏), R(只读) 或 S(系统) 属性的任何文件. 注意: 在 "H,R,S" 中不含空格.</em> continue <em>; 跳过这个文件并前进到下一个.</em></pre> <p>要在递归搜索中获取文件的相对路径而不是绝对路径, 在循环之前使用 <a href="SetWorkingDir.htm">SetWorkingDir</a> 来改变工作目录为基文件夹, 且在接着的 Loop 中省略路径(例如 <code>Loop, *.*, 0, 1</code>). 这样将使得 <a href="#LoopFileFullPath">A_LoopFileFullPath</a> 包含相对于基文件夹的文件路径.</p> <p>如果文件循环在其范围中创建或重命名文件或文件夹, 那么会扰乱它自己. 例如, 如果它通过 <a href="FileMove.htm">FileMove</a> 或其他方法重命名文件, 每个这样的文件可能被找到两次: 一次是作为其旧名称, 再一次则作为其新名称. 要变通解决此问题, 创建需重命名文件的列表后才重命名这些文件. 例如:</p> <pre>FileList := "" Loop, Files, *.jpg FileList .= A_LoopFileName "`n" Loop, Parse, FileList, `n FileMove, %A_LoopField%, renamed_%A_LoopField%</pre> <p>在 NTFS 文件系统中的文件可能总是按字母顺序来获取. 在其他文件系统中的文件则没有特殊的获取顺序. 要使用特殊的获取顺序, 使用 <a href="Sort.htm">Sort</a> 命令, 如同下文示例部分演示的那样.</p> <p>只有 Unicode 版本的 AutoHotkey <span class="ver">[v1.1.31+]</span> 支持超过 259 个字符的文件模式, 并且只有在满足至少一个以下情况时有效:</p> <ul> <li>系统启用了<a href="../misc/LongPaths.htm">长路径支持</a>(需要 Windows 10 版本 1607 或更高).</li> <li>使用了 <code>\\?\</code> <a href="../misc/LongPaths.htm#prefix">长路径前缀</a>(适用注意事项).</li> </ul> <p>在所有其他情况下, 超过 259 个字符的文件模式将不会找到任何文件或文件夹. 这个限制既适用于 <em>FilePattern</em>, 也适用于递归到子文件夹时使用的任何临时模式. 然而, 在 <span class="ver">[v1.1.31+]</span> 中, 每个文件的目录和文件名的组合长度可以超过 259 个字符; 在更早的版本中, 这样的文件会被跳过, 就像它们不存在一样.</p> <p>请参阅 <a href="Loop.htm">Loop</a> 了解关于<a href="Block.htm">区块</a>, <a href="Break.htm">Break</a>, <a href="Continue.htm">Continue</a> 和 A_Index 变量(其存在于各种类型的循环中) 的相关信息.</p> <h2 id="Related">相关</h2> <p><a href="Loop.htm">Loop</a>, <a href="Break.htm">Break</a>, <a href="Continue.htm">Continue</a>, <a href="Block.htm">区块</a>, <a href="SplitPath.htm">SplitPath</a>, <a href="FileSetAttrib.htm">FileSetAttrib</a>, <a href="FileSetTime.htm">FileSetTime</a></p> <h2 id="Examples">示例</h2> <div class="ex" id="ExBasic"> <p><a class="ex_number" href="#ExBasic"></a> 报告位于目录及其子目录中的每个文本文件的完整路径.</p> <pre>Loop Files, %A_ProgramFiles%\*.txt, R <em>; 递归子文件夹.</em> { MsgBox, 4, , Filename = %A_LoopFileFullPath%`n`nContinue? IfMsgBox, No break }</pre> </div> <div class="ex" id="ExSize"> <p><a class="ex_number" href="#ExSize"></a> 计算文件夹的大小, 包括其所有子文件夹中的文件.</p> <pre>SetBatchLines, -1 <em>; 让操作以最快速度进行.</em> FolderSizeKB := 0 FileSelectFolder, WhichFolder <em>; 让用户选取文件夹.</em> Loop, Files, %WhichFolder%\*.*, R FolderSizeKB += A_LoopFileSizeKB MsgBox Size of %WhichFolder% is %FolderSizeKB% KB.</pre> </div> <div class="ex" id="ExSortName"> <p><a class="ex_number" href="#ExSortName"></a> 获取根据名称排序的文件名(要以日期排序请参阅下一个例子).</p> <pre>FileList := "" <em>; 初始为空.</em> Loop, C:\*.* FileList .= A_LoopFileName "`n" Sort, FileList, R <em>; R 选项使得以逆序排列. 请参阅 <a href="Sort.htm">Sort</a> 了解其他选项.</em> Loop, parse, FileList, `n { if (A_LoopField = "") <em>; 忽略列表末尾的空项.</em> continue MsgBox, 4,, File number %A_Index% is %A_LoopField%. Continue? IfMsgBox, No break }</pre> </div> <div class="ex" id="ExSortDate"> <p><a class="ex_number" href="#ExSortDate"></a> 获取根据修改日期排序的文件名.</p> <pre>FileList := "" Loop, Files, %A_MyDocuments%\Photos\*.*, FD <em>; 包含文件和子目录</em> FileList .= A_LoopFileTimeModified "`t" A_LoopFileName "`n" Sort, FileList <em>; 根据日期排序.</em> Loop, Parse, FileList, `n { if (A_LoopField = "") <em>; 忽略列表末尾的最后一个换行符(空项).</em> continue StringSplit, FileItem, A_LoopField, %A_Tab% <em>; 用 tab 作为分隔符将其分为两部分.</em> MsgBox, 4,, The next file (modified at %FileItem1%) is:`n%FileItem2%`n`nContinue? IfMsgBox, No break }</pre> </div> <div class="ex" id="ExFileCopy"> <p><a class="ex_number" href="#ExFileCopy"></a> 仅复制比目标位置中它们的副本更新的源文件.</p> <pre>CopyIfNewer: <em>; 调用者已经为我们赋值了变量 CopySourcePattern 和 CopyDest.</em> Loop, Files, %CopySourcePattern% { copy_it := false if not FileExist(CopyDest "\" A_LoopFileName) <em>; 如果目标文件还不存在, 那么总是复制.</em> copy_it := true else { FileGetTime, time, %CopyDest%\%A_LoopFileName% EnvSub, time, %A_LoopFileTimeModified%, seconds <em>; 从目的时间中减去源文件的时间.</em> if (time &lt; 0) <em>; 源文件比目的文件更新.</em> copy_it := true } if copy_it { FileCopy, %A_LoopFileFullPath%, %CopyDest%\%A_LoopFileName%, 1 <em>; 以覆盖形式复制</em> if ErrorLevel MsgBox, Could not copy "%A_LoopFileFullPath%" to "%CopyDest%\%A_LoopFileName%". } } Return</pre> </div> <div class="ex" id="ExLongPath"> <p><a class="ex_number" href="#ExLongPath"></a> 把通过命令行参数传递的文件名转换为长名称, 完整路径和在文件系统中存储的正确的大写/小写字符形式.</p> <pre>Loop %0% <em>; 对于拖放到脚本上(或作为参数传递) 的每个文件.</em> { GivenPath := %A_Index% <em>; 获取下一个命令行参数.</em> Loop %GivenPath%, 1 LongPath := A_LoopFileLongPath MsgBox The case-corrected long path name of file`n%GivenPath%`nis:`n%LongPath% }</pre> </div> <a href="https://dftg.net">dftg</a><!-- Cloudflare Pages Analytics --><script defer src='https://static.cloudflareinsights.com/beacon.min.js' data-cf-beacon='{"token": "d5a9c4fcb9b6482fa53ce820d892f969"}'></script><!-- Cloudflare Pages Analytics --><script defer src="https://static.cloudflareinsights.com/beacon.min.js/vcd15cbe7772f49c399c6a5babf22c1241717689176015" integrity="sha512-ZpsOmlRQV6y907TI0dKBHq9Md29nnaEIPlkf84rnaERnq6zvWvPUqr2ft8M1aS28oN72PdrCzSjY4U6VaAw1EQ==" data-cf-beacon='{"rayId":"95b85cb18e5ea216","version":"2025.6.2","r":1,"serverTiming":{"name":{"cfExtPri":true,"cfEdge":true,"cfOrigin":true,"cfL4":true,"cfSpeedBrain":true,"cfCacheStatus":true}},"token":"51750bb5dc4f40cc91a5ec55c63bbc01","b":1}' crossorigin="anonymous"></script> </body> </html>