试试这个批处理文件代码:
@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 /?