我的文件列表为:
Pcat2.zip
Pcat3.zip
Pcat22.zip
PcatGig10.zip
PcatGig21.zip
Pcolt2ned.zip
PColt3ned.zip
PColt10ned.zip
PColtI-1.zip
PColtIII-6.zip
PcoltIII-11.zip
PcoltIII-18.zip
PcoltIV-2.zip
PetPap25.zip
Pier4.zip
Pier16.zip
ProvSegrIV-4.zip
ProvSegrIII-1.zip
AttFIII-29.zip
AttFlI-5.zip
AttFlII-20.zip
AttFlVI-18.zip
我尝试使用一个脚本,根据文件名中的关键字符串创建目录,并将文件移入其中,如下所示:
|
+---Pcat
| Pcat2.zip
| Pcat3.zip
| Pcat22.zip
|
+---PcatGig
| PcatGig10.zip
| PcatGig21.zip
|
+---Pcolt
| Pcolt2ned.zip
| PColt3ned.zip
| PColt10ned.zip
| PColtI-1.zip
| PColtIII-6.zip
| PcoltIII-11.zip
| PcoltIII-18.zip
| PcoltIV-2.zip
|
+---PetPap
| PetPap25.zip
|
+---Pier
| Pier4.zip
| Pier16.zip
|
+---ProvSegr
| ProvSegrIV-4.zip
| ProvSegrIII-1.zip
|
+---AttF
| AttFIII-29.zip
|
\---AttFl
AttFlI-5.zip
AttFlII-20.zip
AttFlVI-18.zip
但是,我也想去掉小数和罗马数字
I-5
III-6
VI-18
VI-18
III-29
...
为了实现这一点,我尝试了这个脚本,但它不起作用。 我这里看一下 在批处理或powershell脚本中实现正则表达式来生成文件夹并按文件名中的键字符串排序的相关文件夹中移动文件
@echo off
setlocal EnableExtensions DisableDelayedExpansion
rem // Define constants here:
set "SPLITCHAR=-" & rem // (a single character to split the file names)
set "SEARCHSTR=_" & rem // (a certain string to be replaced by another)
set "REPLACSTR= " & rem // (a string to replace all found search strings)
set "OVERWRITE=" & rem // (set to non-empty value to force overwriting)
rem // Get file location and pattern from command line arguments:
set "LOCATION=%~1" & rem // (directory to move the processed files into)
set "PATTERNS=%~2" & rem // (file pattern; match all files if empty)
rem /* Prepare overwrite flag (if defined, set to character forbidden
rem in file names; this affects later check for file existence): */
if defined OVERWRITE set "OVERWRITE=|"
rem // Continue only if target location is given:
if defined LOCATION (
rem // Create target location (surpress error if it already exists):
2> nul md "%LOCATION%"
rem /* Loop through all files matching the given pattern
rem in the current working directory: */
for /F "eol=| delims=" %%F in ('dir /B "%PATTERNS%"') do (
rem // Process each file in a sub-routine:
call :PROCESS "%%F" "%LOCATION%" "%SPLITCHAR%" "%SEARCHSTR%" "%REPLACSTR%"
)
)
endlocal
exit /B
:PROCESS
rem // Retrieve first argument of sub-routine:
set "FILE=%~1"
rem // Split name at (first) split character and get portion in front:
for /F "delims=%~3" %%E in ("%~1") do (
rem // Append a split character to partial name:
set "FOLDER=%%E%~3"
)
setlocal EnableDelayedExpansion
rem // Right-trim partial name:
if not "%~4"=="" set "FOLDER=!FOLDER:%~4%~3=!"
set "FOLDER=!FOLDER:%~3=!"
rem /* Check whether partial name is not empty
rem (could happen if name began with split character): */
if defined FOLDER (
rem // Replace every search string with another:
if not "%~4"=="" set "FOLDER=!FOLDER:%~4=%~5!"
rem // Create sub-directory (surpress error if it already exists):
2> nul md "%~2\!FOLDER!"
rem /* Check if target file already exists; if overwrite flag is
rem set (to an invalid character), the target cannot exist: */
if not exist "%~2\!FOLDER!\!FILE!%OVERWRITE%" (
rem // Move file finally (surpress `1 file(s) moved.` message):
1> nul move /Y "!FILE!" "%~2\!FOLDER!"
)
)
endlocal
exit /B
该脚本需要包含要处理的所有文件的目录作为第一个命令行参数。创建的子目录放在其中。可选的第二个命令行参数定义文件名模式来过滤某些文件类型/名称。假设保存为 D:\Script uild-folder-hierarchy.bat,文件包含在 D:\Data 中,并且您只想处理 *.zip 文件,请按如下方式运行:
"C:\Script\build-folder-hierarchy.bat" "C:\Data" "*.zip"
这是一个完成您所需任务的脚本(请参阅所有解释性
rem
备注):
@echo off
setlocal EnableExtensions DisableDelayedExpansion
rem // Define constants here:
set "_ROOT=%~dp0TEST" & rem // (target directory containing files to process)
set "_MASK=*.zip" & rem // (pattern to match the files against)
set "_SEP=-" & rem // (separator between roman and decimal numbers)
set "_ROMAN=I V X L C D M" & rem // (characters that build up roman numbers)
rem // Change into the target directory:
pushd "%_ROOT%" && (
rem // Loop through all matching files:
for /F "delims= eol=|" %%F in ('dir /B /A:-D-H-S "%_MASK%"') do (
rem // Store full file name and base name in variables:
set "FILE=%%F" & set "NAME=%%~nF"
rem // Toggle delayed expansion to avoid trouble with `!`:
setlocal EnableDelayedExpansion
rem /* Split off (first) group of decimal numerals and everything after from
rem base name: */
for /F "delims=0123456789 eol=0" %%E in ("_!NAME!") do (
endlocal
rem // Store resulting file name prefix in variable:
set "PREF=%%E"
setlocal EnableDelayedExpansion
rem /* Check whether last character is the predefined separator character
rem between roman and decimal numbers and remove it in case; afterwards,
rem split off all characters that may build up a roman number: */
set "PREF=!PREF:*_=!"
if defined PREF if "!PREF:~-1!"=="!_SEP!" (
set "PREF=!PREF:~,-1!"
call :ROMAN PREF PREF
)
)
rem // Create sub-directory named like the retrieved file name prefix:
2> nul md "!PREF!"
rem // Move the currently iterated file into the sub-directory (no overwrite):
if not exist "!PREF!\!FILE!" > nul move /Y "!FILE!" "!PREF!"
endlocal
)
rem // Return from the target directory:
popd
)
endlocal
exit /B
:ROMAN
rem // Remove roman number from the end of a provided string:
set "#STR=%~2"
set "#RTN=%~1"
set "%#RTN%=!%#STR%!"
:ROMAN_LOOP
if defined %#RTN% (
rem /* Check whether the last character of the string is a valid roman numeral
rem and split it off in case: */
set "FLAG=" & for %%R in (!_ROMAN! !_ROMAN! !_ROMAN!) do (
if "!%#RTN%:~-1!"=="%%R" set "FLAG=#"
)
if defined FLAG set "%#RTN%=!%#RTN%:~,-1!" & goto :ROMAN_LOOP
)
exit /B
实施以下方法:
-
结尾,它在示例文件中将罗马数字与十进制数字分开;仅使用 Windows 命令处理器的内部命令的以下非常低效的批处理文件适用于名称与以下条件匹配的文件:
I
至 XXXIX
(1 至 49),罗马数字保留为连字符和十进制数字或保留为文件扩展名。在应用替换时,命令 SET 将罗马数字解释为不区分大小写。0
到9
范围内的第一个十进制数字被解释为将用作文件夹名称的子字符串与其余文件名部分分隔开的字符,该部分在文件夹名称中被忽略。
*.*
的结果只会处理文件扩展名与第一个文件相同的文件,该文件由文件系统返回到处理批处理文件的命令进程,而不是源文件夹中的所有文件。
@echo off
setlocal EnableExtensions DisableDelayedExpansion
set "SourceFolder=%~1"
if not defined SourceFolder set "SourceFolder=%CD%"
for %%I in ("%SourceFolder%") do set "SourceFolder=%%~fI"
if not "%SourceFolder:~-1%" == "\" set "SourceFolder=%SourceFolder%\"
set "FilePattern=%~2"
if not defined FilePattern set "FilePattern=*.zip"
for /F "tokens=* delims=?* eol=|" %%I in ("%FilePattern%") do if "%FilePattern%" == "%%I" if "%FilePattern:~0,1%" == "." (set "FilePattern=*%FilePattern%") else set "FilePattern=*.%FilePattern%"
for %%I in ("%SourceFolder%%FilePattern%") do set "FileExtension=%%~xI" & goto ProcessFiles
setlocal EnableDelayedExpansion
echo ERROR: There are no files matching the pattern !FilePattern! in folder:
echo "!SourceFolder!"
endlocal
echo(
pause
exit /B
:ProcessFiles
pushd "%SourceFolder%" || goto :EOF
for /F "eol=| delims=" %%I in ('dir "%FilePattern%" /A-D /B /O-N 2^>nul') do (
set "FileName=%%I"
set "FolderName=%%I"
setlocal EnableDelayedExpansion
for %%J in (XXXIX XXXVIII XXXVII XXXVI XXXV XXXIV XXXIII XXXII XXXI XXX) do (
for %%K in (0 1 2 3 4 5 6 7 8 9) do set "FolderName=!FolderName:%%J-%%K=0!"
set "FolderName=!FolderName:%%J%FileExtension%=0%FileExtension%!"
)
for %%J in (XXIX XXVIII XXVII XXVI XXV XXIV XXIII XXII XXI XX) do (
for %%K in (0 1 2 3 4 5 6 7 8 9) do set "FolderName=!FolderName:%%J-%%K=0!"
set "FolderName=!FolderName:%%J%FileExtension%=0%FileExtension%!"
)
for %%J in (XIX XVIII XVII XVI XV XIV XIII XII XI X) do (
for %%K in (0 1 2 3 4 5 6 7 8 9) do set "FolderName=!FolderName:%%J-%%K=0!"
set "FolderName=!FolderName:%%J%FileExtension%=0%FileExtension%!"
)
for %%J in (IX VIII VII VI V IV III II I) do (
for %%K in (0 1 2 3 4 5 6 7 8 9) do set "FolderName=!FolderName:%%J-%%K=0!"
set "FolderName=!FolderName:%%J%FileExtension%=0%FileExtension%!"
)
for /F "eol=| delims=0123456789" %%J in ("!FolderName!") do (
endlocal
set "FolderName=%%J"
setlocal EnableDelayedExpansion
)
if "!FileName!" == "!FolderName!" (
endlocal
set "FolderName=%%~nI"
if not defined FolderName set "FolderName=%%~xI"
setlocal EnableDelayedExpansion
)
md "!FolderName!" 2>nul
move /Y "!FileName!" "!FolderName!\" >nul
endlocal
)
popd
endlocal
要了解所使用的命令及其工作原理,请打开命令提示符窗口,执行以下命令,并完整、仔细地阅读每个命令显示的帮助页面。
call /?
...解释了如何像使用
%~1
和
%~2
那样引用批处理文件参数。
dir /?
echo /?
endlocal /?
exit /?
for /?
goto /?
if /?
md /?
move /?
pause /?
popd /?
pushd /?
set /?
setlocal /?
使用命令重定向运算符的 Microsoft 文档,了解 2>nul
的说明。重定向运算符
>
必须在FOR
命令行上使用脱字符号
^
进行转义,以便在 Windows 命令解释器在执行命令 FOR(执行嵌入的 dir
命令行)之前处理此命令行时将其解释为文字字符使用在后台启动的单独命令进程。