如何编写Windows批处理脚本以从目录复制最新文件?


Answers:


69

Windows外壳,一个内胆:

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

7
默认分隔符为<tab>和<space>,因此最好在FOR / F之后添加“ delims =“以接受带空格的文件名。整体命令将FOR / F “delims =” %% I IN( 'DIR / B / O:-D')DO COPY %%我<< NEWDIR >>&EXIT
Cheburek

1
注意,&前面的空格成为上一个命令的一部分。这让SET感到困扰,它很高兴将尾随空白插入值中。
克里斯·诺

2
@Ashwin:%% I是来自DIR *.* /B /O:-D-的值,因此对于循环的每次迭代,它都是文件名。由于循环在第一次迭代时退出,因此唯一的值是目录中的第一个文件(名称中带有点)。
idbrii 2012年

大家好。如何仅按日期过滤而不按日期和时间过滤?/ O:-D
DextrousDave 2014年

如果要在一批文件上使用它。将其保存在另一个cmd中,并通过“ CMD / C ONE_LINER.CMD”进行调用
路易吉·麦肯奇·布里托

133

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

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

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

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

: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"

4
太好了...我一直在寻找如何获取最新文件,而您给出的代码示例正是我正在寻找此内容的确切原因,它还原了sql服务器备份!
tbone

1
这很有帮助。只需说明一下,如果您的文件不方便位于子目录中(例如我的文件),则可以使用DIR中的“ / S”标志进行递归检查。即在上面的DIR之后插入“ / S”,它应该可以工作。

@ObligatoryMoniker:%% I是什么?
阿什温

如何仅按日期过滤而不按日期和时间过滤?/ O:D
DextrousDave 2014年

1
@Ashwin,%% I是FOR循环中的迭代器
CrazyTim 2014年

11

为了使它可以使用空格处理文件名,需要修改后的答案版本:

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

3
要支持空间,必须进行哪些更改?仅包含“ %% I”周围的引号?
理查兹(Arichards)2015年

5
@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例如

我认为超时无法在winXP上工作


3

@克里斯·诺

注意,&前面的空格成为上一个命令的一部分。这让SET感到困扰,它很高兴将尾随空白插入值中。

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

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


是的,它可以工作,但是标准的方式SET是使用像set "NewestFile=%%I"
jeb

那可能是您的标准,但我的意思是……:-)
理查德(Richard)

但是parens的(set var=&complex^)报价工作失败set "var=&complex^"
jeb 2011年

就是这样。我不记得我上次在BAT中进行按位数学运算的情况。我正在仔细看/ 它明确提到了引号。我已经使用parens多年了。真的不想清理文件-我想我会接受的。毕竟,我都有“ if%1!==!” 和“如果[%1] == []”格式,我就活了下来.... :-)
理查德(Richard)

2

我知道您要求使用Windows,但是我想还是要添加此功能,在Unix / Linux中,您可以这样做:

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

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


我没想到这篇文章会给出这个答案。非常感谢你。
Mrk

2

这将打开第二个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

-2

重击:

 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(假设它们都在相同的搜索范围内)。因此,如果您希望此文件多次运行,则可能必须调整要复制的文件号。

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.