简体   繁体   English

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

[英]issues with enabledelayedexpansion for file renaming batch script

i am writing a batch script monotonic file renamer.我正在编写一个批处理脚本单调文件重命名器。 basically, it makes the titles of all the files 1 2 3 4.... and so on.基本上,它使所有文件的标题为 1 2 3 4.... 等等。 i have since expanded it to be able to handle files of different types (txt, doc, flv, etc) but not everything is working out.我已经将它扩展为能够处理不同类型的文件(txt、doc、flv 等),但并非一切正常。

my main concern is i have broken the delayed expansion calls i was making before.我主要担心的是我已经打破了我之前发出的延迟扩展电话。 now using,var1.现在使用,var1。 is never expanded, or never recognized as a variable.永远不会扩展,或者永远不会被识别为变量。

here is a verbosely commented version of my script这是我的脚本的详细注释版本

::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

the idea is i drop my two files, renamer.bat(this file) and exttostr.bat(helper to get the file extension) into the folder and run it, it will rename files sorted alphabetically from 1 to how ever many files i specify.我的想法是我将我的两个文件 renamer.bat(此文件)和 exttostr.bat(帮助获取文件扩展名)放入文件夹并运行它,它会将按字母顺序从 1 排序的文件重命名为我指定的文件数量.

when i run the code, it never uses the variables marked for delayed expansion appropriately, always leaving them as ",varname.".当我运行代码时,它永远不会适当地使用标记为延迟扩展的变量,总是将它们保留为“,varname。”。 so it renames the first file "!counter!.!type!"所以它重命名第一个文件“!counter!.!type!” and throws errors for the rest because there is already a file in the directory with that name.并为 rest 引发错误,因为目录中已经有一个具有该名称的文件。

this brings me to a secondary issue.这让我想到了一个次要问题。 sorting the dir list alphabetically results in a poor handling of numbered files.按字母顺序对目录列表进行排序会导致对编号文件的处理不佳。 for example the list: "1 7 15 75 120" is sorted: "1 120 15 7 75" i have not been able to find a way around this yet, only that it is indeed the intended result of the dir sort.例如,列表:“1 7 15 75 120”已排序:“1 120 15 7 75”我还没有找到解决方法,只是它确实是 dir 排序的预期结果。 the only workaround i have is padding numbers with enough zeroes in the front.我唯一的解决方法是在前面用足够的零填充数字。

thanks in advance for any insight!提前感谢您的任何见解!


everything is sorted but the second problem.一切都已排序,但第二个问题。 i think i have not spoken well.我想我说得不好。 i have this issue when i take IN the directory file names, not when writing out.当我输入目录文件名而不是写出时,我遇到了这个问题。 so they already need to be padded.所以他们已经需要被填充了。 i has hoping there was some other way to read the directory and have it be sorted appropriately.我希望有其他方法可以读取目录并对其进行适当排序。

the most promising thing i have found is here: http://www.dostips.com/DtCodeBatchFiles.php#Batch.SortTextWithNumbers我发现的最有希望的东西在这里: 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
)

this code can sort the filenames with one number in them (ie video100.mov is fine, video100video10.mov would break it)这段代码可以用一个数字对文件名进行排序(即 video100.mov 很好,video100video10.mov 会破坏它)

the issue i have is i think adding a call to this helper fn will break it again, so i will be trying to include this in my modified renamer.bat now.我遇到的问题是我认为添加对这个助手 fn 的调用会再次破坏它,所以我现在将尝试将它包含在我修改后的 renamer.bat 中。 any help is appreciated.任何帮助表示赞赏。

Probably the batch for extracting the extension reset the local environment.可能用于提取扩展的批处理重置了本地环境。

But, you don't need it.但是,你不需要它。 You may extract the extension with the ~x option.您可以使用~x选项提取扩展名。 Something similar to this....类似的东西......

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

to include leading zeroes in the counter, so that the directory sorts correctly, replace the previous rename command with three lines要在计数器中包含前导零,以便目录正确排序,请将前面的重命名命令替换为三行

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

So putting all pieces together, add the monotonicrename function you just created in the batch file that can be as simpler as...因此,将所有部分放在一起,添加您刚刚在批处理文件中创建的单调重命名 function,它可以像...

@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

I didn't experience any issues with delayed expansion, everything worked fine for me (except, of course, for the fact that I didn't have the exttostr.bat helper script.)我没有遇到任何延迟扩展的问题,一切对我来说都很好(当然,除了我没有exttostr.bat帮助脚本这一事实。)

Anyway, there are several things that could be improved about your script:无论如何,您的脚本有几处可以改进的地方:

  1. You don't need to store the result of DIR into a file to read it afterwards.您无需将DIR的结果存储到文件中以供以后读取。 You can read the output directly in the FOR loop.您可以直接在FOR循环中读取 output。

  2. You don't need the helper batch script.您不需要帮助程序批处理脚本。 The extension can be extracted from %%a by using the ~x modifier with the loop variable: %% ~x a .可以通过使用带有循环变量的~x修饰符从%%a中提取扩展名: %% ~x a You can read more about modifiers by issuing HELP FOR from the command prompt.您可以通过从命令提示符发出HELP FOR来阅读有关修饰符的更多信息。

  3. The renamer batch file's own name can be referenced in the script as %0 .重命名器批处理文件自己的名称可以在脚本中引用为%0 You can apply the ~n modifier where you only need to use the name without the extension.您可以应用~n修饰符,您只需要使用没有扩展名的名称。 The combined modifier of ~nx will give you the name with the extension. ~nx的组合修饰符将为您提供带有扩展名的名称。

So, here's how your script might look like with the above issues addressed:因此,在解决上述问题后,您的脚本可能如下所示:

::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

As for your secondary issue, it can be easily resolved like this:至于您的次要问题,可以像这样轻松解决:

  1. Use something like 100000 as counter 's initial value.使用类似100000作为counter的初始值。 (Use however many 0s you like, but possibly no more than nine.) Add the same value to ender as well. (使用任意数量的 0,但可能不超过 9 个。)也将相同的值添加到ender

  2. When renaming files, instead of !counter!重命名文件时,而不是!counter! use the expression that removes the first character (the 1 ): :counter:~1!使用删除第一个字符( 1 )的表达式: :counter:~1! (in fact, this is not about removal, but about extracting a substring starting from the offset of 1, learn more about it with the HELP SET command). (实际上,这不是关于删除,而是关于从偏移量 1 开始提取 substring,使用HELP SET命令了解更多信息)。

Here's the modified version of the above script:这是上述脚本的修改版本:

::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

You can also see that I made some other enhancements, like making sure the file name is enclosed in double quotes, and using GOTO:EOF instead of GOTO exit ( :EOF is a special pre-defined label that points at the end of the batch script so you don't need to define your own).您还可以看到我进行了一些其他增强,例如确保文件名用双引号括起来,并使用GOTO:EOF而不是GOTO exit:EOF是一个特殊的预定义 label ,它指向批处理的末尾脚本,所以你不需要定义自己的)。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM