Loop (文件和文件夹)

获取指定的文件或文件夹, 每次一个.

新语法 [v1.1.21+]

Loop, Files, FilePattern , Mode

参数

Files

原义单词 Files(大小写敏感). 不可为变量或表达式.

FilePattern(文件模式)

单个文件或文件夹的名称或者通配符模式, 例如 C:\Temp\*.tmp. 如果未指定绝对路径, 则假定 FilePatternA_WorkingDir.

支持星号和问号作为通配符使用. 当模式出现在文件的长/普通名称或其 8.3 短名称时出现匹配.

如果此参数为单个文件或文件夹(即不含通配符) 且 Mode 包含 R, 同时指定的文件名出现在多个被搜索的文件夹中, 那么将找到多个匹配.

由于系统限制(MAX_PATH), 超过 259 个字符的模式可能无法找到任何文件. 这个限制可以通过使用 \\?\ 长路径前缀绕过, 但有一些条件.

Mode(方式)

如果为空或省略, 则只包括文件且不递归子文件夹. 否则, 指定一个或多个下列字母:

传统语法

过时的: 不推荐在新脚本中使用此语法. 而是使用新语法.

Loop, FilePattern , IncludeFolders, Recurse

参数

FilePattern

单个文件或文件夹的名称或者通配符模式, 例如 C:\Temp\*.tmp. 如果未指定绝对路径, 则假定 FilePattern%A_WorkingDir%.

支持星号和问号作为通配符使用. 当模式出现在文件的长/普通名称或其 8.3 短名称时出现匹配.

如果此参数为单个文件或文件夹(即不含通配符) 且 Recurse 值为 1, 同时指定的文件名出现在多个被搜索的文件夹中, 那么将找到多个匹配.

IncludeFolders(包含子文件夹)

如果为空或省略, 则默认为 0. 否则, 指定下列数字之一:

Recurse(递归)

如果为空或省略, 则默认为 0. 否则, 指定下列数字之一:

  • 0 = 不对子文件夹进行递归.
  • 1 = 递归子文件夹, 以便获取包含在其中的匹配 FilePattern 的文件和文件夹. 将递归所有子文件夹, 而不仅是名称匹配 FilePattern 的那些.
  • 可在文件循环中使用的特殊变量

    下列变量存在于任何文件循环中. 如果一个内层文件循环包含在一个外层文件循环中, 那么最内层循环的文件将具有优先权:

    变量 描述
    A_LoopFileName 当前获取的文件或文件夹的名称(不含路径).
    A_LoopFileExt 当前文件的扩展名(例如 TXT, DOC 或 EXE). 不含句点(.).
    A_LoopFileFullPath
    A_LoopFilePath

    当前获取的文件/文件夹的路径和名称. 如果 FilePattern 包含相对路径而不是绝对路径, 那么这里的路径也是相对路径. 此外, FilePattern 中的任何短(8.3) 文件夹名称仍将为短名称(请参阅下一项来获取长名称).

    A_LoopFilePath 可以在 [v1.1.28+] 中使用, 作为 A_LoopFileFullPath 的别名, A_LoopFileFullPath 是一个错误的用词.

    A_LoopFileLongPath

    此变量与 A_LoopFileFullPath 有以下不同之处: 1) 不论 FilePattern 包含的是否为相对路径, 它总是包含文件的绝对/完整路径; 2) 在 FilePattern 中的任何短(8.3) 文件夹名称被转换成它们的长名称; 3) 在 FilePattern 中的字符被转换成与文件系统中存储的名称一致的大小写形式. 把文件名转换为资源管理器中显示的准确路径名称时这很有用, 例如作为命令行参数传递给脚本的那些.

    A_LoopFileShortPath

    当前获取的文件/文件夹的 8.3 短路径和名称. 例如: C:\MYDOCU~1\ADDRES~1.txt. 如果 FilePattern 包含相对路径而不是绝对路径, 那么这里的路径也是相对路径.

    要获取单个文件或文件夹的完整的 8.3 路径和名称, 如下例所示:

    Loop, C:\My Documents\Address List.txt
        ShortPathName := A_LoopFileShortPath

    注意: 如果文件没有短名称, 那么此变量将为 , 这种情况会发生在注册表中设置了 NtfsDisable8dot3NameCreation 的系统上. 如果 FilePattern 包含相对路径且循环体中使用 SetWorkingDir 从当前循环的有效的工作目录中切换出来, 那么它也将为空.

    A_LoopFileShortName 8.3 短名称或文件的备用名称. 如果文件没有此名称(由于长名称比 8.3 形式更短或也许因为在 NTFS 文件系统上禁止生成短名称), 将获取 A_LoopFileName 作为代替.
    A_LoopFileDir A_LoopFileName 所在目录的路径. 如果 FilePattern 包含相对路径而不是绝对路径, 那么这里的路径也是相对路径. 根目录将不包含末尾的反斜杠. 例如: C:
    A_LoopFileTimeModified 文件的上次修改时间. 格式为 YYYYMMDDHH24MISS.
    A_LoopFileTimeCreated 文件的创建时间. 格式为 YYYYMMDDHH24MISS.
    A_LoopFileTimeAccessed 文件的上次访问时间. 格式为 YYYYMMDDHH24MISS.
    A_LoopFileAttrib 当前获取的文件的属性.
    A_LoopFileSize 以字节为单位的当前获取的文件的大小. 同样支持大于 4 GB 的文件.
    A_LoopFileSizeKB 以 KB 为单位的当前获取的文件的大小, 向下取整到最近的整数.
    A_LoopFileSizeMB 以 MB 为单位的当前获取的文件的大小, 向下取整到最近的整数.

    备注

    当您想同时对文件和/或文件夹集合中的项逐个进行操作时, 文件循环很有用.

    所有匹配的文件都被获取, 包括隐藏文件. 相比之下, 诸如 DIR 命令的 OS 特性默认忽略隐藏文件. 要避免处理隐藏, 系统和/或只读文件, 请在循环内部使用类似下面的方法:

    if A_LoopFileAttrib contains H,R,S  ; 跳过具有 H(隐藏), R(只读) 或 S(系统) 属性的任何文件. 注意: 在 "H,R,S" 中不含空格.
        continue  ; 跳过这个文件并前进到下一个.

    要在递归搜索中获取文件的相对路径而不是绝对路径, 在循环之前使用 SetWorkingDir 来改变工作目录为基文件夹, 且在接着的 Loop 中省略路径(例如 Loop, *.*, 0, 1). 这样将使得 A_LoopFileFullPath 包含相对于基文件夹的文件路径.

    如果文件循环在其范围中创建或重命名文件或文件夹, 那么会扰乱它自己. 例如, 如果它通过 FileMove 或其他方法重命名文件, 每个这样的文件可能被找到两次: 一次是作为其旧名称, 再一次则作为其新名称. 要变通解决此问题, 创建需重命名文件的列表后才重命名这些文件. 例如:

    FileList := ""
    Loop, Files, *.jpg
       FileList .= A_LoopFileName "`n"
    Loop, Parse, FileList, `n
       FileMove, %A_LoopField%, renamed_%A_LoopField%

    在 NTFS 文件系统中的文件可能总是按字母顺序来获取. 在其他文件系统中的文件则没有特殊的获取顺序. 要使用特殊的获取顺序, 使用 Sort 命令, 如同下文示例部分演示的那样.

    只有 Unicode 版本的 AutoHotkey [v1.1.31+] 支持超过 259 个字符的文件模式, 并且只有在满足至少一个以下情况时有效:

    在所有其他情况下, 超过 259 个字符的文件模式将不会找到任何文件或文件夹. 这个限制既适用于 FilePattern, 也适用于递归到子文件夹时使用的任何临时模式. 然而, 在 [v1.1.31+] 中, 每个文件的目录和文件名的组合长度可以超过 259 个字符; 在更早的版本中, 这样的文件会被跳过, 就像它们不存在一样.

    请参阅 Loop 了解关于区块, Break, Continue 和 A_Index 变量(其存在于各种类型的循环中) 的相关信息.

    命令 FileGetAttrib, FileGetSize, FileGetTime, FileGetVersion, FileSetAttribFileSetTime 可以在文件循环中使用, 而不需要它们的 Filename/FilePattern 参数.

    Loop, Break, Continue, 区块, SplitPath, FileSetAttrib, FileSetTime

    示例

    报告位于目录及其子目录中的每个文本文件的完整路径.

    Loop Files, %A_ProgramFiles%\*.txt, R  ; 递归子文件夹.
    {
        MsgBox, 4, , Filename = %A_LoopFileFullPath%`n`nContinue?
        IfMsgBox, No
            break
    }

    计算文件夹的大小, 包括其所有子文件夹中的文件.

    SetBatchLines, -1  ; 让操作以最快速度进行.
    FolderSizeKB := 0
    FileSelectFolder, WhichFolder  ; 让用户选取文件夹.
    Loop, Files, %WhichFolder%\*.*, R
        FolderSizeKB += A_LoopFileSizeKB
    MsgBox Size of %WhichFolder% is %FolderSizeKB% KB.

    获取根据名称排序的文件名(要以日期排序请参阅下一个例子).

    FileList := ""  ; 初始为空.
    Loop, C:\*.*
        FileList .= A_LoopFileName "`n"
    Sort, FileList, R  ; R 选项使得以逆序排列. 请参阅 Sort 了解其他选项.
    Loop, parse, FileList, `n
    {
        if (A_LoopField = "")  ; 忽略列表末尾的空项.
            continue
        MsgBox, 4,, File number %A_Index% is %A_LoopField%.  Continue?
        IfMsgBox, No
            break
    }

    获取根据修改日期排序的文件名.

    FileList := ""
    Loop, Files, %A_MyDocuments%\Photos\*.*, FD  ; 包含文件和子目录
        FileList .= A_LoopFileTimeModified "`t" A_LoopFileName "`n"
    Sort, FileList  ; 根据日期排序.
    Loop, Parse, FileList, `n
    {
        if (A_LoopField = "")  ; 忽略列表末尾的最后一个换行符(空项).
            continue
        StringSplit, FileItem, A_LoopField, %A_Tab%  ; 用 tab 作为分隔符将其分为两部分.
        MsgBox, 4,, The next file (modified at %FileItem1%) is:`n%FileItem2%`n`nContinue?
        IfMsgBox, No
            break
    }

    仅复制比目标位置中它们的副本更新的源文件.

    CopyIfNewer:
    ; 调用者已经为我们赋值了变量 CopySourcePattern 和 CopyDest.
    Loop, Files, %CopySourcePattern%
    {
        copy_it := false
        if not FileExist(CopyDest "\" A_LoopFileName)  ; 如果目标文件还不存在, 那么总是复制.
            copy_it := true
        else
        {
            FileGetTime, time, %CopyDest%\%A_LoopFileName%
            EnvSub, time, %A_LoopFileTimeModified%, seconds  ; 从目的时间中减去源文件的时间.
            if (time < 0)  ; 源文件比目的文件更新.
                copy_it := true
        }
        if copy_it
        {
            FileCopy, %A_LoopFileFullPath%, %CopyDest%\%A_LoopFileName%, 1   ; 以覆盖形式复制
            if ErrorLevel
                MsgBox, Could not copy "%A_LoopFileFullPath%" to "%CopyDest%\%A_LoopFileName%".
        }
    }
    Return

    把通过命令行参数传递的文件名转换为长名称, 完整路径和在文件系统中存储的正确的大写/小写字符形式.

    Loop %0%  ; 对于拖放到脚本上(或作为参数传递) 的每个文件.
    {
        GivenPath := %A_Index%  ; 获取下一个命令行参数.
        Loop %GivenPath%, 1
            LongPath := A_LoopFileLongPath
        MsgBox The case-corrected long path name of file`n%GivenPath%`nis:`n%LongPath%
    }