【问题标题】:forfiles command ignore a directoryforfiles 命令忽略目录
【发布时间】:2016-01-12 23:12:51
【问题描述】:

我想编写一个批处理,在 c:\ 中找到所有小于 50 mb 的文档并将它们复制到一个文件夹中但忽略系统目录文档。我更喜欢它甚至不在系统目录中搜索。

这是我的批处理,它在正确的目录中找到并复制所有小于 50 mb 的文件,但我不能让它忽略系统搜索或 C:\Windows 目录。

@ECHO off
:: variables

SET odrive=%odrive:~0,2%
SET backupcmd=xcopy /s /c /d /e /h /i /r /y

MKDIR "C:\Users\Documents\USBBackups\DOC\C"

forfiles /P C:\ /M *.DOC* /S /C "cmd /c if @fsize leq 50000000 echo @PATH "  > "C:\Users\Documents\USBBackups\DOCC.txt"
FOR /F "tokens=*" %%a in (C:\Users\Documents\USBBackups\DOCC.txt) do xcopy %%a "C:\Users\Documents\USBBackups\DOC\C" /c /h /i /r /y

@ECHO off

【问题讨论】:

    标签: batch-file cmd command-line


    【解决方案1】:

    当提供开关/S 时,无法告诉forfiles 排除某些目录。您必须编写自己的代码来执行此操作。

    由于性能不佳,我不会使用forfiles,而是使用标准for

    @echo off
    for /D %%D in ("%SystemDrive%\*.*") do (
        if /I not "%%D"=="%SystemRoot%" (
            pushd "%%D"
            for /R %%F in ("*.doc?") do (
                if %%~zF LEQ 50000000 (
                    echo %%F
                )
            )
            popd
        )
    )
    

    这里的根目录级别由for /D 枚举。 %SystemRoot%以外的所有目录都由for /R递归枚举。

    我将搜索模式从*.doc* 更改为*.doc?,以便不包括以.doc.lnk 结尾的文件,我猜你不想被检索到。

    代替echo 命令,您可以直接将xcopy 命令行与"%%F" 提供作为复制源。


    你可以直接在命令提示符下做同样的事情,就像这样:

    for /D %D in ("%SystemDrive%\*.*") do @if /I not "%D"=="%SystemRoot%" pushd "%D" & (for /R %F in ("*.doc?") do @if %~zF LEQ 50000000 echo %F) & popd
    

    我建议不要遍历整个目录树,然后通过 findstr /V /I /L /B /C:"%SystemRoot%" 之类的内容进行过滤,因为在这种情况下,您会浪费时间枚举大量后来忽略的项目。

    但是,如果您确实想依赖 forfiles /S,则工作命令行如下所示:

    2> nul forfiles /S /P "C:\\" /M "*.doc*" /C "cmd /C if @isdir==FALSE if @fsize LEQ 50000000 echo @path" | findstr /V /I /L /B /C:"\"%SystemRoot%"
    

    【讨论】:

    • 非常感谢您的帮助。你有什么技巧可以提高代码性能和速度
    • 不客气!我无法真正提高使用嵌套for 循环的方法的性能;但是,为了使其更快,您也许可以排除更多文件夹(如C:\Program Files);或者另一个想法是不排除(a)某些文件夹,而只包括专用文件夹,因为这也可能减少文件夹的总数......
    • 感谢您的提示,顺便说一下,我如何将您的单行代码(用于 /D ...)的结果保存到一个 .txt 文件中,就像我的 forfiles 代码中的那个一样。我真的试过了,但它在每个循环中都会覆盖记事本
    • 只需将整行包含在()中,然后将`> "\path\to\textfile.txt" 放在行的开头或结尾(因此文件只写一次而不是比逐行)...
    • 抱歉,当我将其作为批处理文件运行时出现此错误“在批处理参数替换中路径运算符的以下用法无效:%~zF LEQ 50000000 echo %F( & popd) > "C:\Users\Documents\USBBackups\DOCC.txt""
    【解决方案2】:

    采用这种使用findstr 的技术来过滤掉某些名称。

    查看文档中文件夹的大小,不包括音乐、视频或图片文件夹。

    for /f "skip=3 tokens=3" %A in ('Reg query "HKCU\Software\Microsoft\Windows\CurrentVersion\Explorer\User Shell Folders" /v "Personal"') do set doc=%A
    
    for /f "usebackq tokens=2* delims= " %i IN (`dir "%doc%" /a /s ^|findstr /i /v "\/"^|findstr /l /v "Pictures Music Video"`) DO @echo %j&echo.
    

    但是,您可以在 c:\users 或特定用户主文件夹 (%userprofile%) 中启动 forfiles 命令。您指定从包含所有文件夹的 c:\ 开始。

    forfiles /P %userprofile% /M .DOC /S /C "cmd /c if @fsize leq 50000000 echo @PATH "
    forfiles /P c:\users /M .DOC /S /C "cmd /c if @fsize leq 50000000 echo @PATH "
    

    【讨论】:

      猜你喜欢
      • 2013-02-05
      • 2015-04-14
      • 2016-04-21
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2019-10-04
      • 1970-01-01
      相关资源
      最近更新 更多