【问题标题】:How to move files from a source directory to a destination directory with name of first part of file name?如何将文件从源目录移动到具有文件名第一部分名称的目标目录?
【发布时间】:2018-09-12 01:40:14
【问题描述】:

我已经用help of others编写了下面的批处理文件,但是我没有太多经验,所以这对我来说有点困难。

我正在尝试将 PDF 文件从特定位置传输到另一个位置的单个文件夹。每个文件名都采用这种格式RANSOM-NH_2018-08-07_5485A635.pdf,并且基于RANSOM-NH_,批处理文件应将PDF文件传输/移动到名为RANSOM-NH_Ransom INC的正确文件夹中。因此,根据文件名的开头部分,将文件移动到名称以文件名开头部分开头的文件夹中。

文件和文件夹名称的一些示例:

文件名:

RANSOM-NH_2018-06-20_2018_5849.pdf
GREENWOOD_2018-07-02_66902.pdf
GLSCIENCES_2018-07-24_24811.pdf
CPI_2018-08-01_20039035.pdf
ALDR_2018-08-08_545477636.pdf
ACCQTRAX_2018-07-26_173845.pdf

文件夹名称:

RANSOM-NH_Ransom INC
GREENWOOD_Greenwood Products, Inc
GLSCIENCES_GL Sciences, Inc
CPI_CPI International
ALDR_Sigma-Aldrich, Inc
ACCQTRAX_AccQtrax

我遇到的问题是,编写的脚本仍然将文件 RANSOM-NH8_ 移动到它根本不应该做的同一文件夹中。

@ECHO OFF
SETLOCAL
SET "sourcedir=C:\Users\Alpha\Documents\NOTEPAD Coding\File Transfer Coding\Files"
SET "destdir=C:\Users\Alpha\Documents\NOTEPAD Coding\File Transfer Coding\Transfer"
FOR /f "delims=" %%a IN ('dir /b /a-d "%sourcedir%\*.pdf" ') DO (
    FOR /f "tokens=1 delims=_-" %%b IN ("%%a") DO (
        FOR /f "delims=" %%d IN ('dir /b /ad "%destdir%\*%%b*" ') DO (
            MOVE "%sourcedir%\%%a" "%destdir%\%%d\"
        )
    )
)
GOTO :EOF

【问题讨论】:

    标签: windows batch-file cmd


    【解决方案1】:

    试试这个批处理文件代码:

    @echo off
    setlocal EnableExtensions DisableDelayedExpansion
    set "SourceDir=%UserProfile%\Documents\NOTEPAD Coding\File Transfer Coding\Files"
    set "DestDir=%UserProfile%\Documents\NOTEPAD Coding\File Transfer Coding\Transfer"
    
    for /F "eol=| delims=" %%A in ('dir /B /A-D-H "%SourceDir%\*_????-??-??_*.pdf" 2^>nul') do (
        for /F "eol=| tokens=1 delims=_" %%B in ("%%~nA") do (
            for /D %%C in ("%DestDir%\%%B_*") do move /Y "%SourceDir%\%%A" "%%C\"
        )
    )
    
    endlocal
    

    第一个 FOR 在命令行后台以cmd.exe /C 开头的单独命令进程中执行:

    dir /B /A-D-H "C:\Users\Alpha\Documents\NOTEPAD Coding\File Transfer Coding\Files\*_????-??-??_*.pdf" 2>nul
    

    DIR在指定目录中搜​​索

    • 只是非隐藏文件,因为/A-D-H(属性不是目录,也不是隐藏)
    • 匹配通配符模式*_????-??-??_*.pdf,也可能只是*_*.pdf
    • 并输出以裸格式处理 STDOUT,因为 /B 只是带​​有文件扩展名的文件名,但没有文件路径。

    DIR 输出的错误消息用于处理 STDERR 如果指定的目录根本不存在或没有与模式匹配的文件通过使用 @ 重定向来抑制987654331@ 到设备 NUL

    阅读有关Using Command Redirection Operators 的Microsoft 文档,了解2>nul 的解释。当 Windows 命令解释器在执行命令 FOR 在后台启动的单独命令进程中执行嵌入的dir 命令行。

    FOR 捕获写入已启动命令进程的 STDOUT 的所有内容,并逐行处理捕获的输出。

    FOR 默认忽略所有空行(此处不出现)和所有以分号开头的行。文件名可以以分号开头。因此,选项eol=| 用于将行尾字符重新定义为文件名不能包含的竖线,请参阅Microsoft 文档页面Naming Files, Paths, and Namespaces

    FOR 还将使用空格/制表符作为分隔符将每一行拆分为子字符串(标记),并将仅将第一个空格/制表符分隔的字符串分配给指定的循环变量A。此处不需要这种拆分行为,因为文件名可以包含一个或多个空格字符。因此,选项delims= 用于定义一个空的分隔符列表,该列表完全禁用行拆分,并导致将带有扩展名的整个文件名分配给循环变量A

    第二个FOR 仅将文件名(不带扩展名)处理为字符串。这次文件名使用下划线作为分隔符进行拆分,因为delims=_ 仅将第一个下划线分隔的字符串分配给循环变量B,因为tokens=1。好吧,tokens=1 是使用 for /F 的默认值,因此可以从代码中删除此选项字符串。

    所以第一个 FOR 分配给A,例如RANSOM-NH_2018-08-07_5485A635.pdf,第二个FOR 处理RANSOM-NH_2018-08-07_5485A635 并分配给B 字符串RANSOM-NH .

    带有选项/D 的第三个FOR 搜索目标目录中的非隐藏目录,以分配给循环变量B 的字符串和下划线开头。如果找到这样的目录,则将其名称和完整路径分配给循环变量C 并执行命令MOVE

    文件从源移动到目标目录中的现有子目录,并覆盖文件目标目录中同名的现有文件。

    第二个 FOR 循环可以在没有以下划线开头的 PDF 文件或在日期部分之前有多个下划线的 PDF 文件时被优化掉。

    @echo off
    setlocal EnableExtensions DisableDelayedExpansion
    set "SourceDir=%UserProfile%\Documents\NOTEPAD Coding\File Transfer Coding\Files"
    set "DestDir=%UserProfile%\Documents\NOTEPAD Coding\File Transfer Coding\Transfer"
    
    for /F "eol=| tokens=1* delims=_" %%A in ('dir /B /A-D-H "%SourceDir%\*_????-??-??_*.pdf" 2^>nul') do (
        for /D %%C in ("%DestDir%\%%A_*") do move /Y "%SourceDir%\%%A_%%B" "%%C\"
    )
    
    endlocal
    

    选项 tokens=1* 导致根据ASCII table 将文件名的第一个下划线分隔部分分配给循环变量A 并将文件名的其余部分分配给下一个循环变量B,而无需进一步拆分下划线。

    但请注意优化后的版本不适用于类似文件名

    • _RANSOM-X_2018-08-07_5485A635.pdf ... 开头的下划线,或
    • RANSOM-Y__2018-08-07_5485A635.pdf ... 不止一个下划线到日期部分。

    优化后的版本可以进一步优化为单个命令行:

    @for /F "eol=| tokens=1* delims=_" %%A in ('dir /B /A-D-H "%UserProfile%\Documents\NOTEPAD Coding\File Transfer Coding\Files\*_????-??-??_*.pdf" 2^>nul') do @for /D %%C in ("%UserProfile%\Documents\NOTEPAD Coding\File Transfer Coding\Transfer\%%A_*") do @move /Y "%UserProfile%\Documents\NOTEPAD Coding\File Transfer Coding\Files\%%A_%%B" "%%C\"
    

    嗯,未优化的版本也可以写成更长的单命令行:

    @for /F "eol=| delims=" %%A in ('dir /B /A-D-H "%UserProfile%\Documents\NOTEPAD Coding\File Transfer Coding\Files\*_????-??-??_*.pdf" 2^>nul') do @for /F "eol=| tokens=1 delims=_" %%B in ("%%~nA") do @for /D %%C in ("%UserProfile%\Documents\NOTEPAD Coding\File Transfer Coding\Transfer\%%B_*") do @move /Y "%UserProfile%\Documents\NOTEPAD Coding\File Transfer Coding\Files\%%A" "%%C\"
    

    要了解所使用的命令及其工作原理,请打开命令提示符窗口,在其中执行以下命令,并仔细阅读每个命令显示的所有帮助页面。

    • dir /?
    • echo /?
    • endlocal /?
    • for /?
    • move /?
    • set /?
    • setlocal /?

    【讨论】:

      猜你喜欢
      • 2023-04-10
      • 2020-04-11
      • 2015-12-01
      • 2014-06-06
      • 1970-01-01
      • 2020-06-09
      • 2022-11-15
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多