проблемы с enabledelayedexpansion для пакетного сценария переименования файлов - PullRequest
2 голосов
/ 29 июня 2011

Я пишу монотонный файл переименования пакетного сценария.в основном, это делает названия всех файлов 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 ]

4 голосов
/ 29 июня 2011

Вероятно, пакет для извлечения расширения сбрасывает локальную среду.

Но тебе это не нужно. Вы можете извлечь расширение с помощью опции ~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 

Итак, собрав все части вместе, добавьте функцию монотонного имени, которую вы только что создали в командном файле, которая может быть проще, чем ...

@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 голос
/ 29 июня 2011

У меня не было проблем с отложенным расширением, у меня все работало нормально (за исключением, конечно, того факта, что у меня не было вспомогательного скрипта exttostr.bat.)

В любом случае,Есть несколько вещей, которые могут быть улучшены в вашем сценарии:

  1. Вам не нужно сохранять результат DIR в файле для последующего его чтения.Вы можете прочитать вывод непосредственно в цикле FOR.

  2. Вам не нужен вспомогательный сценарий пакетной обработки.Расширение можно извлечь из %%a с помощью модификатора ~x с переменной цикла: %%<b>~x</b>a.Вы можете узнать больше о модификаторах, введя HELP FOR из командной строки.

  3. На собственное имя пакетного файла переименования можно сослаться в сценарии как %0.Вы можете применить модификатор ~n, когда вам нужно использовать только имя без расширения.Комбинированный модификатор ~nx даст вам имя с расширением.

Итак, вот как ваш скрипт может выглядеть с указанными выше проблемами:

::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, но, возможно, не более девяти.) Также добавьте это значение к ender.

  2. При переименовании файлов вместо !counter! используйтеВыражение, которое удаляет первый символ (1): !counter:~1! (на самом деле речь идет не об удалении, а о извлечении подстроки, начиная со смещения 1, узнайте больше об этом с помощью команды HELP SET).

Вот модифицированная версия вышеуказанного скрипта:

::a monotonic file renamer
@echo off
SETLOCAL ENABLEDELAYEDEXPANSION

IF [%1] == [] GOTO usage

::initialize 
SET /A counter=<b>1000</b>
SET type=
SET /A ender=%1
<b>SET /A ender+=counter</b>

::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" "<b>!counter:~1!</b>%%~xa"
    ECHO Renamed "%%~a" to "<b>!counter:~1!</b>%%~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 - это специальная предопределенная метка, которая указывает на конец пакетного сценария, поэтому вам не нужно определять свой собственный).

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...