我在其他人的帮助下编写了下面的批处理文件,但我没有太多经验,所以这对我来说有点困难。
我正在尝试将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:UsersAlphaDocumentsNOTEPAD CodingFile Transfer CodingFiles"
SET "destdir=C:UsersAlphaDocumentsNOTEPAD CodingFile Transfer CodingTransfer"
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
试试这个批处理文件代码:
@echo off
setlocal EnableExtensions DisableDelayedExpansion
set "SourceDir=%UserProfile%DocumentsNOTEPAD CodingFile Transfer CodingFiles"
set "DestDir=%UserProfile%DocumentsNOTEPAD CodingFile Transfer CodingTransfer"
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:UsersAlphaDocumentsNOTEPAD CodingFile Transfer CodingFiles*_????-??-??_*.pdf" 2>nul
DIR在指定目录中搜索
- 只是由于
/A-D-H
而非隐藏文件(属性不是目录,也不是隐藏) - 匹配通配符模式
*_????-??-??_*.pdf
,也可以只是*_*.pdf
- 和输出以处理裸格式的STDOUT,因为
/B
只有文件扩展名的文件名,但没有文件路径。
如果指定的目录根本不存在,或者没有与模式匹配的文件,则DIR输出的用于处理STDERR的错误消息将通过2>nul
重定向到设备NUL来抑制。
阅读有关使用命令重定向运算符的Microsoft文档,了解2>nul
的说明。当 Windows 命令解释器在执行命令 FOR 之前处理此命令行时,重定向运算符>
必须使用FOR命令行上的插入字符^
进行转义,该命令使用在后台启动的单独命令进程执行嵌入的dir
命令行。
FOR捕获写入已启动命令进程的STDOUT的所有内容,并逐行处理捕获的输出。
默认情况下,FOR忽略所有空行(此处不会出现)和所有以分号开头的行。文件名可以以分号开头。因此,选项eol=|
用于将行尾字符重新定义为文件名无法包含的竖线,请参阅Microsoft文档页面命名文件、路径和命名空间。
FOR 还会使用空格/制表符作为分隔符将每行拆分为子字符串(标记),并且仅将第一个空格/制表符分隔的字符串分配给指定的循环变量A
。此处不需要此拆分行为,因为文件名可以包含一个或多个空格字符。因此,选项delims=
用于定义一个空的分隔符列表,该列表完全禁用行拆分,并导致将带有扩展名的整个文件名分配给循环变量A
。
第二个FOR仅将文件名(不带扩展名)作为字符串处理。这次文件名使用下划线作为分隔符进行拆分,因为delims=_
由于tokens=1
而只将第一个下划线分隔的字符串分配给循环变量B
。好吧,tokens=1
是使用for /F
的默认设置,因此可以从代码中删除此选项字符串。
因此,第一个 FOR 分配给A
例如RANSOM-NH_2018-08-07_5485A635.pdf
和第二个FOR进程RANSOM-NH_2018-08-07_5485A635
并分配给B
字符串RANSOM-NH
。
第三个FORwith 选项/D
搜索目标目录中的非隐藏目录,从分配给循环变量B
的字符串和下划线开始。如果找到这样的目录,则将其具有完整路径的名称分配给循环变量C
并执行命令MOVE。
将文件从源目录移动到目标目录中的现有子目录,并覆盖文件目标目录中同名的现有文件。
当从来没有以下划线开头的 PDF 文件或在日期部分之前有多个下划线时,第二个FOR循环可以优化掉。
@echo off
setlocal EnableExtensions DisableDelayedExpansion
set "SourceDir=%UserProfile%DocumentsNOTEPAD CodingFile Transfer CodingFiles"
set "DestDir=%UserProfile%DocumentsNOTEPAD CodingFile Transfer CodingTransfer"
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 表将文件名的第一个下划线分隔部分分配给循环变量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%DocumentsNOTEPAD CodingFile Transfer CodingFiles*_????-??-??_*.pdf" 2^>nul') do @for /D %%C in ("%UserProfile%DocumentsNOTEPAD CodingFile Transfer CodingTransfer%%A_*") do @move /Y "%UserProfile%DocumentsNOTEPAD CodingFile Transfer CodingFiles%%A_%%B" "%%C"
好吧,未优化的版本也可以写成更长的单个命令行:
@for /F "eol=| delims=" %%A in ('dir /B /A-D-H "%UserProfile%DocumentsNOTEPAD CodingFile Transfer CodingFiles*_????-??-??_*.pdf" 2^>nul') do @for /F "eol=| tokens=1 delims=_" %%B in ("%%~nA") do @for /D %%C in ("%UserProfile%DocumentsNOTEPAD CodingFile Transfer CodingTransfer%%B_*") do @move /Y "%UserProfile%DocumentsNOTEPAD CodingFile Transfer CodingFiles%%A" "%%C"
要了解使用的命令及其工作原理,请打开命令提示符窗口,在那里执行以下命令,并仔细阅读为每个命令显示的所有帮助页面。
dir /?
echo /?
endlocal /?
for /?
move /?
set /?
setlocal /?