【问题标题】:Check if files in a directory are still being written using Windows Batch Script检查目录中的文件是否仍在使用 Windows 批处理脚本写入
【发布时间】:2010-03-29 23:07:35
【问题描述】:

这是我解析目录的批处理文件,以及特定类型的压缩文件

 REM Begin ------------------------
    tasklist /FI "IMAGENAME eq 7za.exe" /FO CSV > search.log
    FOR /F %%A IN (search.log) DO IF %%~zA EQU 0 GOTO end
    for /f "delims=" %%A in ('dir C:\Temp\*.ps /b') do (
"C:\Program Files\7-Zip\cmdline\7za.exe" a -tzip -mx9 "C:\temp\Zip\%%A.zip" "C:\temp\%%A"
Move "C:\temp\%%A" "C:\Temp\Archive"
)
    :end
    del search.log
    REM pause
    exit
    REM End ---------------------------

这段代码可以很好地满足我 90% 的需求。它将作为计划任务部署。

但是,在实时情况下,*.ps 文件相当大(最小为 1GB)。所以代码应该检查传入的文件是否已完全写入并且没有被正在编写它的应用程序锁定。

我在其他地方看到了另一个示例,建议采用以下方法

:TestFile
ren c:\file.txt c:\file.txt
if errorlevel 0 goto docopy
sleep 5
goto TestFile
:docopy

不过,这个例子适用于固定文件。如何在 for 循环中使用这么多标签和 GoTo 而不会导致无限循环?或者这段代码在 For 循环中使用是否安全?

感谢您的帮助。

【问题讨论】:

    标签: windows command-line batch-file archive


    【解决方案1】:

    我同意 GOTO 循环是有风险的——一个错误会导致它永远循环,这对于计划任务来说一点也不好。

    对于这样的任务,我倾向于使用Resource Kit tool called Robocopy,部分原因是它速度很快,但也因为它很健壮。如果文件未准备好(/w:10),我通常将其设置为重试 3-5 次(选项 /r:3),暂停 10 秒(/w:10),然后让它记录任何错误,以便我查看它们(/log:...) .非常便利。这是the full list of options,它可以帮助您准确地选择您需要复制的内容。

    我的第一反应可能有点草率。小重命名技巧可以集成到您的脚本中,并且可能会正常工作:

    ...
    for /f "delims=" %%A in ('dir C:\Temp\*.ps /b') do (
    :TestFile
    ren C:\Temp\%%A.ps C:\Temp\%%A.ps
    if errorlevel 0 goto Continue
    sleep 5
    goto TestFile
    :Continue
    "C:\Program Files\7-Zip\cmdline\7za.exe" a -tzip -mx9 "C:\temp\Zip\%%A.zip" "C:\temp\%%A"
    move "C:\temp\%%A" "C:\Temp\Archive"
    )
    ...
    

    或者,如果您想使用 Robocopy,您可以先移动文件,然后再进行压缩。 (只要您将文件移动到同一个分区上——在你的例子中,它是从 C:\TEMP 到 C:\TEMP\Archived——没有延迟。)这样 Robocopy 将一直等到文件准备好,然后让你的脚本继续压缩。这是一个例子:

    ...
    for /f "delims=" %%A in ('dir C:\Temp\*.ps /b') do (
    robocopy C:\Temp C:\Temp\Archive\ %%A.ps /mov /r:100 /w:5 /log+:copylog.txt
    "C:\Program Files\7-Zip\cmdline\7za.exe" a -tzip -mx9 "C:\temp\Archive\%%A.zip" "C:\temp\Archive\%%A.ps"
    )
    ...
    

    【讨论】:

    • 即使重命名尝试失败,上面的 ren 命令也会返回 ErrorLevel 为 0。我们如何真正识别重命名失败?
    • 我的测试表明,对于失败的重命名,ErrorLevel 设置为 1,就像复制、移动等失败一样。而且 robocopy 选项仍然可以工作。 :)
    【解决方案2】:

    以下是我最终使用的批处理文件脚本。它非常适合要求。我希望它可以帮助与我有相同要求的人。

    tasklist /FI "IMAGENAME eq 7za.exe" /FO CSV > search.log
    FOR /F %%%A IN (search.log) DO IF %%%~zA EQU 0 GOTO end
    for /f "delims=" %%A in ('dir C:\Temp\ZIP\*.txt /b') do (
         :TestFile 
        "C:\Program Files\7-Zip\cmdline\7za.exe" a -tzip -mx9 "C:\temp\Zip\ZipDone%%A.zip" "C:\temp\zip\%%A"
         Move "C:\temp\ZIP\%%A" "C:\Temp\ZIP\Archive"
         )
    :end
    del search.log
    REM pause
    Exit
    

    【讨论】:

      猜你喜欢
      • 2011-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2015-07-09
      • 2018-12-08
      • 1970-01-01
      • 2013-04-11
      • 1970-01-01
      相关资源
      最近更新 更多