enabledelayedexpansion对文件重命名批处理脚本的问题

时间:2011-06-29 03:28:25

标签: windows batch-file

我正在编写一个批处理脚本单调文件重命名器。基本上,它使所有文件的标题1 2 3 4 ....等等。我已经扩展它以便能够处理不同类型的文件(txt,doc,flv等),但并非一切都正常。

我主要担心的是我已经打破了我以前制作的延迟扩展电话。现在使用!var1!永远不会扩展,或永远不会被识别为变量。

这是我的脚本的详细评论版本

::a monotonic file renamer
@echo off
SETLOCAL ENABLEDELAYEDEXPANSION

SET tempfile=temp.txt
SET exttemp=exttemp.txt
if [%1] == [] goto usage

::make sure your dont overwrite something useful
if EXIST %tempfile% (
ECHO Temp file already exists, are you sure you want to delete?
del /P %tempfile%
)
if EXIST %exttemp% (
ECHO EXT Temp file already exists, are you sure you want to delete?
del /P %exttemp%
)

::initialize 
SET /a counter=0
SET type=
SET /a ender=%1

::write filenames to tempfile
DIR /B /ON > %tempfile%

::read lines one by one
for /f "usebackq delims=" %%a in (%tempfile%) do (
REM make sure we do not rename any of the working files
if NOT "%%a"=="renamer.bat" (
if NOT "%%a"=="temp.txt" (
if NOT "%%a"=="exttostr.bat" (
SET /a counter+=1
REM get file extension
exttostr %%a > %exttemp%
SET /P type= < %exttemp%
REM housekeeping
del /F %exttemp%
REM rename
ren %%a !counter!.!type!
ECHO Renamed "%%a" to "!counter!.!type!"
)))
REM exit when we have run enough
if "!counter!"=="!ender!" goto exit
)

goto exit

:usage
echo Usage: renamer NUMFILES

:exit
::final housekeeping
DEL temp.txt

我的想法是将我的两个文件renamer.bat(此文件)和exttostr.bat(帮助程序获取文件扩展名)放入文件夹并运行它,它将按字母顺序重命名文件从1到多少我指定的文件。

当我运行代码时,它从不使用标记为延迟扩展的变量,总是将它们保留为“!varname!”,因此它重命名第一个文件“!counter!。!type!”并且因为目录中已存在具有该名称的文件而导致其余的错误。

这让我想到了第二个问题。按字母顺序排序目录列表​​会导致对编号文件的处理不当。例如列表: “1 7 15 75 120” 排序: “1 120 15 7 75” 我还没有找到解决方法,只是它确实是dir排序的预期结果。我唯一的解决方法是填充前面有足够零的数字。

提前感谢任何见解!


一切都是排序但第二个问题。我想我说话不好。当我接收目录文件名时,我有这个问题,而不是在写出时。所以他们已经需要填补。我希望有其他方法来读取目录并对其进行适当的排序。

我发现的最有希望的是:http://www.dostips.com/DtCodeBatchFiles.php#Batch.SortTextWithNumbers

    @ECHO OFF
if "%~1"=="/?" (
    echo.Sorts text by handling first number in line as number not text
    echo.
    echo.%~n0 [n]
    echo.
    echo.  n     Specifies the character number, n, to
    echo.        begin each comparison.  3 indicates that
    echo.        each comparison should begin at the 3rd
    echo.        character in each line.  Lines with fewer
    echo.        than n characters collate before other lines.
    echo.        By default comparisons start at the first
    echo.        character in each line.
    echo.
    echo.Description:
    echo.        'abc10def3' is bigger than 'abc9def4' because
    echo.        first number in first string is 10
    echo.        first number in second string is 9
    echo.        whereas normal text compare returns 
    echo.        'abc10def3' smaller than 'abc9def4'
    echo.
    echo.Example:
    echo.        To sort a directory pipe the output of the dir
    echo.        command into %~n0 like this:
    echo.           dir /b^|%~n0
    echo.
    echo.Source: http://www.dostips.com
    goto:EOF
)

if "%~1" NEQ "~" (
    for /f "tokens=1,* delims=," %%a in ('"%~f0 ~ %*|sort"') do echo.%%b
    goto:EOF
)
SETLOCAL ENABLEDELAYEDEXPANSION
set /a n=%~2+0
for /f "tokens=1,* delims=]" %%A in ('"find /n /v """') do (
    set f=,%%B
    (
        set f0=!f:~0,%n%!
        set f0=!f0:~1!
        rem call call set f=,%%%%f:*%%f0%%=%%%%    
        set f=,!f:~%n%!
    )
    for /f "delims=1234567890" %%b in ("!f!") do (
        set f1=%%b
        set f1=!f1:~1!
        call set f=0%%f:*%%b=%%
    )
    for /f "delims=abcdefghijklmnopqrstuwwxyzABCDEFGHIJKLMNOPQRSTUWWXYZ~`@#$*_-+=:;',.?/\ " %%b in ("!f!") do (
        set f2=00000000000000000000%%b
        set f2=!f2:~-20!
        call set f=%%f:*%%b=%%
    )
    echo.!f1!!f2!!f!,%%B
    rem echo.-!f0!*!f1!*!f2!*!f!*%%a>&2
)

此代码可以对文件名进行排序,其中包含一个数字(即video100.mov很好,video100video10.mov会破坏它)

我的问题是我认为添加对此帮助程序fn的调用将再次打破它,所以我将尝试将此包含在我的修改后的renamer.bat中。任何帮助表示赞赏。

2 个答案:

答案 0 :(得分:4)

用于提取扩展名的批处理可能会重置本地环境。

但是,你不需要它。您可以使用~x选项提取扩展名。与此相似......

:monotonicrename
set /a counter = 0
for %%a in (%1\*.*) do (
  if exist %%~fa (
    set /a counter += 1
    echo ren %%~fa !counter!%%~xa 
  )
)
goto :eof

在计数器中包含前导零,以便目录正确排序,用三行替换以前的重命名命令

set zcounter=0000!counter!
set zcounter=!zcounter:~-4!
echo ren %%~fa !counter!%%~xa 

因此,将所有部分组合在一起,在批处理文件中添加刚创建的monotonicrename函数,该函数可以更简单...

@echo off
setlocal enabledelayedexpansion
call :monotonicrename %1
goto :eof
:monotonicrename
set /a counter = 0
for %%a in (%1\*.*) do (
  if exist %%~fa (
    set /a counter += 1
    set zcounter=0000!counter!
    set zcounter=!zcounter:~-4!
    echo ren %%~fa !zcounter!%%~xa 
  )
)
goto :eof

答案 1 :(得分:1)

我没有遇到延迟扩展的任何问题,一切对我来说都很好(当然,除了我没有exttostr.bat帮助脚本这一事实。)

无论如何,关于你的脚本有几点可以改进:

  1. 您无需将DIR的结果存储到文件中以便以后读取它。您可以直接在FOR循环中阅读输出。

  2. 您不需要帮助程序批处理脚本。可以使用%%a修饰符和循环变量~x%%~xa中提取扩展名。您可以通过从命令提示符发出HELP FOR来阅读有关修饰符的更多信息。

  3. 重命名器批处理文件的名称可以在脚本中引用为%0。您可以应用~n修饰符,只需使用不带扩展名的名称。 ~nx的组合修饰符将为您提供扩展名。

  4. 因此,以下是解决上述问题的脚本的样子:

    ::a monotonic file renamer
    @echo off
    SETLOCAL ENABLEDELAYEDEXPANSION
    
    IF [%1] == [] GOTO usage
    
    ::initialize 
    SET /A counter=0
    SET type=
    SET /A ender=%1
    
    ::read lines one by one
    FOR /F "usebackq delims=" %%a IN (`DIR /B /ON`) DO (
      REM make sure we do not rename any of the working files
      IF NOT "%%~a"=="%~nx0" (
        SET /A counter+=1
        RENAME "%%~a" "!counter!%%~xa"
        ECHO Renamed "%%~a" to "!counter!%%~xa"
      )
      REM exit when we have run enough
      IF "!counter!"=="!ender!" GOTO :EOF
    )
    
    GOTO :EOF
    
    :usage
    ECHO Usage: %~n0 NUMFILES
    

    关于您的次要问题,可以像这样轻松解决:

    1. 使用100000之类的内容作为counter的初始值。 (但是你喜欢使用多少0,但可能不超过9个。)同样的值也添加到ender

    2. 重命名文件时,而不是!counter!使用删除第一个字符(1)的表达式:!counter:~1!(事实上,这不是关于删除,而是关于从偏移量1开始提取子字符串,使用HELP SET命令了解更多信息。

    3. 以下是上述脚本的修改版本:

      ::a monotonic file renamer
      @echo off
      SETLOCAL ENABLEDELAYEDEXPANSION
      
      IF [%1] == [] GOTO usage
      
      ::initialize 
      SET /A counter=1000
      SET type=
      SET /A ender=%1
      SET /A ender+=counter
      
      ::read lines one by one
      FOR /F "usebackq delims=" %%a IN (`DIR /B /ON`) DO (
        REM make sure we do not rename any of the working files
        IF NOT "%%~a"=="%~nx0" (
          SET /A counter+=1
          RENAME "%%~a" "!counter:~1!%%~xa"
          ECHO Renamed "%%~a" to "!counter:~1!%%~xa"
        )
        REM exit when we have run enough
        IF "!counter!"=="!ender!" GOTO :EOF
      )
      
      GOTO :EOF
      
      :usage
      ECHO Usage: renamer NUMFILES
      

      您还可以看到我做了一些其他增强功能,例如确保文件名用双引号括起来,并使用GOTO :EOF代替GOTO exit:EOF是一个特殊的增强功能 - 指向批处理脚本末尾的定义标签,因此您无需定义自己的标签。