【问题标题】:For loop in batch file reading a file of File Paths批处理文件中的循环读取文件路径文件
【发布时间】:2012-01-20 23:18:36
【问题描述】:

我想编写一个 Windows 批处理文件脚本,它将遍历 FILE PATHS 的文本文件,使用每个文件路径中的数据做一些工作,然后最终删除该文件。

我首先运行 FORFILES 命令并发送其输出(@PATH 参数是它匹配的任何文件的完整路径)到一个文本文件 (results.txt)。

我最终得到一个如下的 results.txt 文件:

"C:/Windows/Dir1/fileA.log"
"C:/Windows/Dir1/fileA.log"
"C:/Windows/Dir2/fileC.log" 
"C:/Windows/Dir3/fileB.log"

我想做的是:

  • 使用 FOR 循环并读取 results.txt 文件中的每一行
  • 对于每一行(文件路径),去掉日志文件所在的目录名称(即:Dir1、Dir2 等)并在不同的位置创建一个具有相同名称的目录(即 D :/Archive/Backups/Dir1、D:/Archive/Backups/Dir2 等)——假设目录不存在。
  • 将实际的 .log 文件移动到该目录中的一个 zip 文件中 [我有执行此操作的代码]。
  • 从原始位置删除 .log 文件。 [非常简单]

我无法找出完成前 2 个步骤的最佳方法。读完第一行后,我的 FOR 循环似乎停止了:

FOR /F "tokens=1,2,3,4,5,6,7,8,9,10 delims=\" %%G in ("results.txt") DO (
...
)

【问题讨论】:

    标签: windows shell batch-file


    【解决方案1】:

    您不想使用标记/分隔符选项解析路径,因为您不知道要处理多少目录级别。您希望完整地保留每一行。要解析路径,您要使用 FOR 变量修饰符。 (从命令行输入 HELP FOR 并查看输出的最后一部分)

    %%~pG 给出路径(不包括驱动器或文件名)。如果我们然后去掉最后一个\,我们可以通过另一个 FOR 迭代并使用 %%~nxA 获取文件目录的名称(和可能的扩展名)。

    延迟扩展的切换只是为了防止路径中可能出现!。如果您知道没有路径包含!,那么您只需在脚本顶部启用延迟扩展即可。

    编辑 - 自从 Aacini 指出我误读了要求以来,此代码已进行了重大修改。现在应该可以满足要求了。

    for /f "usebackq delims=" %%G in ("results.txt") do (
      set "myPath=%~pG"
      setlocal enableDelayedExpansion
      for /f "eol=: delims=" %%A in ("!myPath:~0,-1!") do (
        endlocal
        if not exist d:\Archive\Backups\%%~nxA md d:\Archive\Backups\%%~nxA
        rem ::zip %%G into zip file in the D: location
        rem ::you should be able to create the zip with the move option
        rem ::so you don't have to del the file
      )
    )
    

    【讨论】:

    • 但是没有一个修饰符给出路径中的最后一个目录...在示例中,D: 的目录与 C: 的目录不同
    • @Aacini - 啊,我没有仔细阅读这个问题。我再试一次
    • 谢谢@dbenham。只是一个小的更正—— set myPath 行不需要双引号。 results.txt 也没有。我不确定它是否会使 results.txt 无效,但肯定是 myPath。通过这几个更正,我能够创建任何新的目录,并且压缩应该非常简单。
    • 糟糕 = 前导引号放错了位置。它应该与更正的引号一起使用,带有“usebackq”选项的“results.txt”也应该如此。但它应该在没有引号的情况下也能正常工作。
    【解决方案2】:

    我在卸载到 SFTP 之前将其写入时间戳文件。

    希望你觉得它有用。

    时间戳编码似乎与您的问题无关,但我留下了它,因为它是剖析文件名本身的一个很好的例子。

    我建议你在 REN 命令前面加一个 ECHO 进行测试。不同的shell可能有不同的结果。

    最后,delayedexpansion 命令是没有必要的。正是这个子程序解决了我在循环内的变量问题。这可能是因为我的操作系统版本。 (Win 8.1) - 离开它不会有什么坏处。

    @echo off
    cls
    setlocal enabledelayedexpansion
    if %time:~0,2% geq 10 set TIMESTAMP=%date:~10,4%%date:~4,2%%date:~7,2%_%time:~0,2%%time:~3,2%%time:~6,2%
    if %time:~0,2% leq 9  set TIMESTAMP=%date:~10,4%%date:~4,2%%date:~7,2%_0%time:~1,1%%time:~3,2%%time:~6,2%
    
    echo TimeStamp=%TIMESTAMP%
    echo.
    
    for %%G in (*.txt) do (
    set OLDNAME=%%G
    call :MXYZPTLK
    )
    
    dir *.txt
    
    goto :EOF
    
    :MXYZPTLK
    echo OldName=%OLDNAME%
    ren %OLDNAME% %OLDNAME:~0,-4%_%TIMESTAMP%%OLDNAME:~-4,4%
    echo.
    
    :END
    

    【讨论】:

      【解决方案3】:

      你有两个小问题:

      • 文件中的路径分隔符是“/”,但您在 for 循环中使用了“\”。
      • “results.txt”周围的引号使其无法正常工作。

      这行得通。不要在 results.txt 中写引号,你不会在文件名的末尾得到引号。

      @echo off
      FOR /F "tokens=3,4 delims=/" %%I in (results.txt) DO (
        REM Directory
        echo %%I
        REM File
        echo %%J
      )
      

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 2015-09-13
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2022-10-21
        • 1970-01-01
        相关资源
        最近更新 更多