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

时间:2018-12-18 21:56:22

标签: windows batch-file cmd windows-console

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

This question/answer正是我想要的,但是当指定/s选项(如this comment would suggest)时,它似乎没有排序:

FOR /F "delims=|" %%I IN ('DIR "K:\path\tp\source\dir\*.ext" /B /S /O:D') DO SET NewestFile=%%I
copy "%NewestFile%" "C:\path\to\destination\dir"

您可以单独测试DIR "K:\path\tp\source\dir\*.ext" /B /S /O:D来查看它是否排序。

我尝试过的事情:该命令本身确实有效:DIR "K:\path\tp\source\dir\*.ext" /S /B | sort,但我不知道如何在for循环中使用它(批处理文件在退出之前就可以退出了)确定错误-即使结尾处带有pause

有什么想法吗?

请参阅:dir docs

3 个答案:

答案 0 :(得分:1)

如果需要,您可以从批处理文件中调出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:\path\to\source\dir"
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:\path\to\dest\dir"

答案 1 :(得分:1)

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

@echo off
    setlocal enableextensions disabledelayedexpansion

    set "root=K:\path\tp\source\dir"
    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生成带有时间戳前缀的文件列表(交换机仅请求无作业头,无作业摘要,无文件类,无文件大小,时间戳,递归,无目录列表,没有目录信息副本,包括相同的文件,没有重试,没有等待,不要只复制生成列表。

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

由于robocopy行包含日期,时间和文件名,要检索最后一个字段,我们请求for /f检索两个令牌:一个包含小时(将存储在{{ 1}}),其余文本直到行尾(存储在%%a中)

包含附加的%%b只是为了防止使用for %%r时出现常见问题。在引用路径以防止空格问题时,我们需要确保路径不以反斜杠结尾,以使路径的右引号转义并使命令失败。

答案 2 :(得分:0)

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

我还建议使用"tokens=*"代替传统的Set "String=",因为在许多情况下空格可能会成为问题。我在功能中对此进行了更新。

批处理脚本:

Set String=