【问题标题】:How do I write a Windows batch script to copy the newest file from a directory?如何编写 Windows 批处理脚本以从目录中复制最新文件?
【发布时间】:2010-09-10 23:23:20
【问题描述】:

我需要将目录中的最新文件复制到新位置。到目前为止,我在forfiles 命令、date-related question 这里和另一个related question 上找到了资源。我只是有一点麻烦把碎片放在一起!如何将该目录中的最新文件复制到新位置?

【问题讨论】:

    标签: batch-file forfiles


    【解决方案1】:

    接受的答案给出了在命令中使用最新文件然后退出的示例。如果您需要在具有其他复杂操作的 bat 文件中执行此操作,您可以使用以下内容将最新文件的文件名存储在变量中:

    FOR /F "delims=" %%I IN ('DIR "*.*" /A-D /B /O:D') DO SET "NewestFile=%%I"
    

    现在您可以在 bat 文件的其余部分中引用 %NewestFile%

    例如,这里是我们用来从目录中获取最新版本的数据库 .bak 文件,将其复制到服务器,然后恢复 db:

    :Variables
    SET DatabaseBackupPath=\\virtualserver1\Database Backups
    
    echo.
    echo Restore WebServer Database
    FOR /F "delims=|" %%I IN ('DIR "%DatabaseBackupPath%\WebServer\*.bak" /B /O:D') DO SET NewestFile=%%I
    copy "%DatabaseBackupPath%\WebServer\%NewestFile%" "D:\"
    
    sqlcmd -U <username> -P <password> -d master -Q ^
    "RESTORE DATABASE [ExampleDatabaseName] ^
    FROM  DISK = N'D:\%NewestFile%' ^
    WITH  FILE = 1,  ^
    MOVE N'Example_CS' TO N'C:\Program Files\Microsoft SQL Server\MSSQL.1\MSSQL\Example.mdf',  ^
    MOVE N'Example_CS_log' TO N'C:\Program Files\Microsoft SQL Server\MSSQL.1\MSSQL\Example_1.LDF',  ^
    NOUNLOAD,  STATS = 10"
    

    【讨论】:

    • 太棒了...我正在寻找如何获取最新文件,而您提供的代码示例正是我正在寻找这个的确切原因,正在恢复 sql server 备份!
    • 这很有帮助。只是要说明一下,如果您的文件不方便地放在子目录中(就像我的那样),您可以使用 DIR 中的 '/S' 标志进行递归检查。即在上面的 DIR 之后插入“/S”,它应该可以工作。
    • @ObligatoryMoniker : %%I 是什么?
    • 如何仅按日期而不按日期和时间过滤? /O:D
    • @Ashwin, %%I 是 FOR 循环中的迭代器
    【解决方案2】:

    Windows 外壳,一层:

    FOR /F "delims=" %%I IN ('DIR *.* /A-D /B /O:-D') DO COPY "%%I" <<NewDir>> & EXIT
    

    【讨论】:

    • 默认分隔符是 因此最好在 FOR /F 之后添加 "delims=" 以接受带有空格的文件名。整个命令将是 FOR /F "delims=" %%I IN ('DIR . /B /O:-D') DO COPY %%I > & EXIT
    • 请注意,&前面的空格成为上一个命令的一部分。这让我对 SET 感到厌烦,它很乐意将尾随空格放入值中。
    • @Ashwin: %%I 是来自DIR *.* /B /O:-D 的值——因此对于循环的每次迭代,它都是文件名。由于循环在第一次迭代时退出,它的唯一值是目录中的第一个文件(名称中带有一个点)。
    • 大家好。如何仅按日期而不是日期和时间过滤? /O:-D
    • @idbrii "(名称中带有一个点)" *.* 具有特殊的行为来匹配不带点的文件,与 * 相同。 (顺便说一句,即使像 *.*.*.* 这样的东西也可以。)
    【解决方案3】:

    为了允许使用空格处理文件名,需要修改版本的已接受答案:

    FOR /F "delims=" %%I IN ('DIR . /B /O:-D') DO COPY "%%I" <<NewDir>> & GOTO :END
    :END
    

    【讨论】:

    • 支持空格需要哪些更改?只有 "%%I" 周围的引号?
    【解决方案4】:
    @echo off
    set source="C:\test case"
    set target="C:\Users\Alexander\Desktop\random folder"
    
    FOR /F "delims=" %%I IN ('DIR %source%\*.* /A:-D /O:-D /B') DO COPY %source%\"%%I" %target% & echo %%I & GOTO :END
    :END
    TIMEOUT 4
    

    我尝试从文件夹中复制最新文件

    只需设置您的源和目标文件夹,它应该可以工作

    这个忽略文件夹,只关心文件

    建议您在 DIR 路径中选择文件类型,例如将 *.* 更改为 *.zip

    我认为TIMEOUT在winXP上不起作用

    【讨论】:

      【解决方案5】:

      我知道你要求 Windows,但我想我还是会添加这个,在 Unix/Linux 中你可以这样做:

      cp `ls -t1 | head -1` /somedir/
      

      这将列出当前目录中的所有文件,按修改时间排序,然后将最新的 cp 到 /somedir/

      【讨论】:

      • 我没想到会在这篇文章中得到这个答案。非常感谢。
      【解决方案6】:

      这将打开第二个 cmd.exe 窗口。如果您希望它消失,请将 /K 替换为 /C。

      显然,将 new_file_loc 替换为您的新文件位置。

      @echo off
      for /F %%i in ('dir /B /O:-D *.txt') do (
          call :open "%%i"
          exit /B 0
      )
      :open
          start "window title" "cmd /K copy %~1 new_file_loc"
      exit /B 0
      

      【讨论】:

        【解决方案7】:

        @Chris Noe

        请注意,& 前面的空格将成为上一个命令的一部分。 这让我对 SET 感到厌烦,它很乐意将尾随空格放入值中。

        要绕过添加到环境变量的尾随空格,请将 set 命令包装在括号中。

        例如FOR /F %%I IN ('DIR "*.*" /B /O:D') DO (SET NewestFile=%%I)

        【讨论】:

        • 是的,它有效,但SET 的标准方法是使用set "NewestFile=%%I" 之类的引号
        • 这可能是你的标准,但我的是parens... :-)
        • 但是 (set var=&amp;complex^) 引号的括号失败 set "var=&amp;complex^"
        • 就是这样。我不记得我上次在 BAT 中进行按位数学是什么时候了。我在细读集合/?它明确提到了引号。多年来我一直在使用parens。真的不想清理文件 - 我想我会忍受它。毕竟,我有两个“如果 %1!==!”和“如果 [%1]==[]” 格式,我活了下来.... :-)
        • 这个确切的表达式对我来说失败了,“%%I was unexpected at this time” - Windows 10,所有当前更新。
        【解决方案8】:

        将基于date 的最新文件从一个目录复制到另一个目录

        echo off
        rem copying latest file with current date from one folder to another folder
        cls
        echo Copying files. Please wait...
        :: echo Would you like to do a copy?
        rem pause
        for /f "tokens=1-4 delims=/ " %%i in ("%date%") do (
             set dow=%%i
             set month=%%j
             set day=%%k
             set year=%%l
        )
        :: Pad digits with leading zeros e.g Sample_01-01-21.csv
            set yy=%year:~-2%
        :: Alternate way - set datestr=%date:~0,2%-%date:~3,2%-%date:~6,2%
        set datestr=%day%-%month%-%yy%
        :: echo "\\networkdrive\Test\Sample_%datestr%.csv"
        rem copy files from src to dest e.g copy <src path> <dest path>
        copy "D:\Source\Sample_%datestr%.csv" D:\Destination
        echo Completed
        rem pause
        

        Save 上面的代码使用.bat 文件格式并根据需要更改目录并运行batch 文件。

        【讨论】:

          【解决方案9】:

          重击:

           find -type f -printf "%T@ %p \n" \
               | sort  \
               | tail -n 1  \
               | sed -r "s/^\S+\s//;s/\s*$//" \
               | xargs -iSTR cp STR newestfile
          

          其中“newestfile”将成为最新文件

          或者,你可以做 newdir/STR 或者只是 newdir

          细分:

          1. 以 {time} {file} 格式列出所有文件。
          2. 按时间排序
          3. 得到最后一个
          4. 从开始/结束处截断时间和空格
          5. 复制结果值

          重要

          运行一次后,最新的文件将是您刚刚复制的内容:p(假设它们都在同一个搜索范围内)。 因此,如果您希望它多次工作,您可能需要调整您复制的文件编号。

          【讨论】:

            猜你喜欢
            • 2010-11-22
            • 1970-01-01
            • 2013-03-01
            • 1970-01-01
            • 1970-01-01
            • 2013-10-18
            • 2012-02-02
            • 1970-01-01
            • 2011-01-01
            相关资源
            最近更新 更多