Windows 'dir'命令:指定'/s'时按日期对文件进行排序



>目标:我想使用批处理文件将具有特定扩展名的最新文件从"源目录"复制到"目标目录"。最新文件可能位于源目录中的多个子目录下。

这个问题/答案正是我想要的,但是当指定/s选项时,它似乎没有排序(正如此评论所建议的那样):

FOR /F "delims=|" %%I IN ('DIR "K:pathtpsourcedir*.ext" /B /S /O:D') DO SET NewestFile=%%I
copy "%NewestFile%" "C:pathtodestinationdir"

您可以单独测试DIR "K:pathtpsourcedir*.ext" /B /S /O:D以查看它是否不排序。

我尝试过什么:这个命令本身确实有效:DIR "K:pathtpsourcedir*.ext" /S /B | sort但我无法弄清楚如何在 for 循环中使用它(批处理文件在我确定错误之前退出 - 即使最后有一个pause)。

有什么想法吗?

请参阅:目录文档

如果需要,可以从批处理文件中调用Powershell。 此代码可以在较新版本的Powershell上缩短。

for /F "delims=" %%G IN ('powershell "gci -rec | where { ! $_.PSIsContainer } | sort LastWriteTime | select -last 1 | Select-Object fullname"') do set NewestFile=%%G

完整答案:

cd /d "K:pathtosourcedir"
for /F "delims=" %%G IN ('powershell "gci -rec *.ext | where { ! $_.PSIsContainer } | sort LastWriteTime | select -last 1 | Select-Object fullname"') do set NewestFile=%%G
copy "%NewestFile%" "C:pathtodestdir"

一个简单的解决方案可能是

@echo off
setlocal enableextensions disabledelayedexpansion
set "root=K:pathtpsourcedir"
set "mask=*.ext"
for %%r in ("%root%.") do for /f "tokens=2,*" %%a in ('
robocopy "%%~fr" "%%~fr" "%mask%" /njh /njs /nc /ns /ts /s /ndl /nocopy /is /r:0 /w:0 /l
^| sort /r 
^| cmd /v /e /c"(set /p .=&echo(!.!)"
') do set "lastFile=%%b"
echo Last file : "%lastFile%"

此代码使用robocopy生成带有时间戳前缀的文件列表(开关只是请求没有作业标头、没有作业摘要、没有文件类、没有文件大小、时间戳、递归、没有目录列表、没有目录信息复制、包含相同的文件、不重试、不等待、不复制仅生成列表)。

然后,此时间戳前缀列表(UTFyyyy/mm/dd hh:mm:ss上次文件写入)按相反顺序排序,以获取第一行中的最后一个文件。此行使用单独的cmd实例进行检索(这避免了for /f读取长数据列表的时间问题),因此for /f只读取一行。

由于robocopy行包含日期、时间和文件名,为了检索最后一个字段,我们请求for /f检索两个标记:一个包含小时(将以%%a形式存储)和直到行尾的其余文本(存储在%%b中)

包括额外的for %%r只是为了防止使用robocopy出现常见问题。当我们引用路径以防止空格问题时,我们需要确保路径不会以反斜杠结尾,该反斜杠将转义路径的结束引号并使命令失败。

一切似乎都正常。我相信您的问题在于您原始函数的"delims=|"语句。通过使用"delims="它所做的只是切断循环输出的第一个|。由于|不在正常的Windows文件路径中,因此完全不需要。尝试在语句中抛出一个"tokens=*"

我还建议使用Set "String="而不是传统的Set String=,因为在许多情况下,空格可能是一个问题。我在函数中更新了它。

批处理脚本:

@ECHO OFF
Rem | Configuration
Set "MainDirectory=C:Folder1"
Set "FileExtension=*.txt"
Set "CopyDestination=C:Folder2"
Rem | Search for the newest file in a directory/sub-directory
for /f "tokens=*" %%A in ('DIR "%MainDirectory%%FileExtension%" /B /S /O:D') do (SET "NewestFile=%%A")
Rem | Copy file to a destination
copy "%NewestFile%" "%CopyDestination%"
goto :EOF

最新更新