【问题标题】:copying most recent file set from txt in unknown directory从未知目录中的 txt 复制最新的文件集
【发布时间】:2016-04-04 11:30:33
【问题描述】:

我有一个 notepad.txt 文档,其中列出了需要复制到保存批处理文件的文件夹中的文件。这些文件位于几个子目录中,并且使用我的代码,它会复制具有指定名称的所有文件。

for /f "delims=" %%i in (testlist.txt) do echo |robocopy "%dir1%." "C:\temporary" "%%i.*" /s /ndl /njs /njh /nc /ts /ns

如何正确设置它以便搜索最新的文件,并且只复制文件而不是文件夹和子文件夹?

【问题讨论】:

  • 您是指testlist.txt 中列出的所有文件中的最新文件,还是某个目录(树)中的文件?
  • testlist.txt 列表中的最新文件。

标签: windows batch-file cmd


【解决方案1】:

How to get file's last modified date on Windows command line?

for %a in (MyFile.txt) do set FileDate=%~ta

Compare 2 dates in a Windows batch file

set "sdate1=%olddate:~-4%%olddate:~3,2%%olddate:~0,2%"
set "sdate2=%newdate:~-4%%newdate:~3,2%%newdate:~0,2%"
if %sdate1% GTR %sdate2% (goto there)  else echo here

鉴于您已经可以读取文件并进行复制,以下是我将编写的逻辑伪代码:

set oldTimeStamp = "1901-01-01" //so first comparison wins and doesn't throw a null error
for each filename in list.txt
   set newTimestamp = getTimeStamp(filename)
   if newTimeStamp > oldTimeStamp then set fileToCopy = filename
   set oldTimeStamp = newTimeStamp
next
doCopy(fileToCopy)

基本上循环遍历每个文件名并获取时间戳。存储前一个文件的时间戳,比较新旧时间戳。如果当前文件较新,请将文件名保存到您将用于复制的变量中。在循环结束时,fileToCopy 应该包含最近修改时间的文件的名称。

【讨论】:

    【解决方案2】:

    以下代码 sn-p 检索最新文件并回显其路径。这里wmic 命令用于获取标准化的独立于语言环境的时间戳,可以立即将其作为字符串进行比较,因此无需将它们转换为数字。所以这里是:

    @echo off
    setlocal EnableExtensions EnableDelayedExpansion
    
    set "RECENT=00000000000000.000000+000"
    set "RECENTFILE="
    for /F "usebackq eol=| delims=" %%L in ("testlist.txt") do (
        setlocal DisableDelayedExpansion
        set "CURRFILE=%%~fL"
        if exist "%%~fL" (
            setlocal EnableDelayedExpansion
            for /F "skip=1 tokens=1 delims= " %%T in ('
                wmic DATAFILE ^
                WHERE Name^="!CURRFILE:\=\\!" ^
                GET LastModified ^
                /FORMAT:TABLE
            ') do (
                for /F "delims=" %%S in ("%%T") do (
                    if %%S GTR !RECENT! (
                        endlocal
                        endlocal
                        set "RECENT=%%S"
                        set "RECENTFILE=%%~fL"
                    ) else (
                        endlocal
                        endlocal
                    )
                )
            )
        ) else (
            endlocal
        )
    )
    if defined RECENTFILE (
        rem Perform your action here:
        echo(!RECENTFILE!
    )
    
    endlocal
    exit /B
    

    会发生什么:

    • 有两个变量RECENTRECENTFILE 分别保存最新文件的时间戳和路径;
    • 外部for /F循环遍历列表文件testlist.txt中的项目;
    • 对于每个现有项目,执行wmic查询以获取最后修改日期,其输出由两个嵌套的for /F循环解析,每个循环仅迭代一次;由于 wmic 返回 Unicode 字符串,单个 for /F 循环是不够的,因为它会留下一些孤立的回车字符,这可能会影响剩余的代码,但第二个循环会删除它们;
    • 将检索到的文件日期与RECENT中的缓冲日期进行比较,如果较大,则表示文件较新,则将其存储在RECENT中,并将相应的文件路径存储在RECENTFILE中;
    • 如果变量RECENTFILE最终没有定义,则列表testlist.txt不指向现有文件,或者为空;
    • 延迟扩展的切换对于避免任何特殊字符的麻烦是必要的;

    除了wmic 查询在性能方面比使用for(例如for %F in ("*.*") do echo %~tF)获取时间戳更差这一事实之外,还存在以下限制:

    , 字符不得出现在任何列出的文件路径中!

    根据this answer,有一种方法可以克服这个问题,但是)字符是不允许的:将子句WHERE Name^="!CURRFILE:\=\\!"替换为WHERE ^(Name^="!CURRFILE:\=\\!"^)(只需要括号的转义^因为wmic 命令行被放置在for /F 集中)。因此,您可以在 wmic 命令行中使用 ,),但不能同时使用这两个字符。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2013-06-25
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多