批处理文件中的循环

时间:2017-05-11 12:42:17

标签: batch-file for-loop

我有一个批处理脚本:

@echo off

setlocal enableDelayedExpansion 
SET /P UserInput=Please Enter a Number:
SET /A number=UserInput
ECHO number=%number%
for %%i in (*.jpeg) do call :JPG %%~ni %%i 
goto :end

:JPG
set str=%1
set /a str2=%str:_color=%
set /a newnamej=%str2%+%number%
echo %1 ==> I can see the problem with it
set lastnamej=%newnamej%_color.jpeg
ren %2 %lastnamej%
goto :eof

:end

此脚本的目标是将所有文件放在一个文件夹中。它们都以数字(1_color.jpeg,2_color.jpeg,3_color.jpeg,..)命名,我想用一个额外的数字重命名它们(如果用户输入为5,则1_color.jpeg将变为6_color.jpeg,并且等等)。 我有这个脚本的问题。 如果我使用诸如555之类的数字,则第一个文件将在for循环中传递2次。

(小例子:1_color.jpeg和2_color.jpeg,

我使用我的脚本5,所以1_color.jpeg => 6_color.jpeg和2_color.jpeg => 7_color.jpeg然后,6_color.jpeg将再次被读取,并将变为11_color.jpeg,所以我的结果将是11_color.jpeg和7_color.jpeg)。
有人知道如何解决这个问题吗?

谢谢大家!

1 个答案:

答案 0 :(得分:1)

用户Aacinihis answer中提供了一个很好的解决方案,指出了两个问题,即for未提前完全枚举目录的事实(请参阅此主题:{ {3}})以及关于处理文件的排序顺序的逻辑缺陷。

但是,仍然存在一个问题,即dir /B /O:-N *.jpeg的纯(反向)字母排序顺序,它仍然可能导致冲突,如下例所示:

9_color.jpeg
8_color.jpeg
7_color.jpeg
6_color.jpeg
5_color.jpeg
4_color.jpeg
3_color.jpeg
2_color.jpeg
10_color.jpeg
1_color.jpeg

因此,如果输入的数字为1,则会尝试将文件9_color.jpeg重命名为10_color.jpeg,因为该文件尚未处理(因此已重命名),因此该文件已失败到11_color.jpeg)。

要解决此问题,您需要以反向字母数字顺序正确排序项目。这可以通过在排序之前对数字进行左零填充来实现,因为这样,字母和字母数字排序顺序匹配。这是一个可能的实现:

@echo off
setlocal EnableExtensions DisableDelayedExpansion

rem // Define constants here:
set "_LOCATION=."       & rem // (directory containing the files to rename)
set "_PATTERN=*_*.jpeg" & rem // (search pattern for the files to rename)
set "_REGEX1=^[0-9][0-9]*_[^_].*\.jpeg$" & rem // (`findstr` filter expression)
set "_TEMPFILE=%TEMP%\%~n0_%RANDOM%.tmp" & rem // (path to temporary file)

rem // Retrieve numeric user input:
set "NUMBER="
set /P NUMBER="Please Enter a number: "
set /A "NUMBER+=0"
if %NUMBER% GTR 0 (set "ORDER=/R") else if %NUMBER% LSS 0 (set "ORDER=") else exit /B
rem /* Write `|`-separated list of left-zero-padded file prefixes, original and new
rem    file names into temporary file: */
> "%_TEMPFILE%" (
    for /F "tokens=1* delims=_" %%E in ('
        dir /B "%_LOCATION%\%_PATTERN%" ^| findstr /I /R /C:"%_REGEX1%"
    ') do (
        set "NAME=%%F"
        setlocal EnableDelayedExpansion
        set "PADDED=0000000000%%E"
        set /A "NUMBER+=%%E"
        echo !PADDED:~-10!^|%%E_!NAME!^|!NUMBER!_!NAME!
        endlocal
    )
)
rem /* Read `|`-separated list from temporary file, sort it by the left-zero-padded
rem    prefixes, extract original and new file names and perform actual renaming: */
< "%_TEMPFILE%" (
    for /F "tokens=2* delims=|" %%K in ('sort %ORDER%') do (
        ECHO ren "%%K" "%%L"
    )
)
rem // Clean up temporary file:
del "%_TEMPFILE%"

endlocal
exit /B

成功验证脚本的正确输出后,不要忘记删除ECHO命令行前面的大写ren命令

该脚本使用一个临时文件,该文件接收一个| - 分隔的表,第一个是填充数字前缀,第二个是原始文件名,第三列是新文件名,如下所示: / p>

0000000010|10_color.jpeg|11_color.jpeg
0000000001|1_color.jpeg|2_color.jpeg
0000000002|2_color.jpeg|3_color.jpeg
0000000003|3_color.jpeg|4_color.jpeg
0000000004|4_color.jpeg|5_color.jpeg
0000000005|5_color.jpeg|6_color.jpeg
0000000006|6_color.jpeg|7_color.jpeg
0000000007|7_color.jpeg|8_color.jpeg
0000000008|8_color.jpeg|9_color.jpeg
0000000009|9_color.jpeg|10_color.jpeg

临时文件由sort命令读取和排序。提取第二列和第三列中的字符串并将其传递给ren命令。