Более 20 лет я использую Total Commander (условно-бесплатное программное обеспечение) для задач переименования файлов / папок, что позволяет с помощью встроенного инструмента многократного переименования легко переименовывать файлы и папки с помощью всего нескольких щелчков мыши, по которым результаты могут быть просмотренным до того, как вы действительно запустите многократное переименование, и которое даже поддерживает отмену после выполнения многократного переименования. Ну, на самом деле я использую Total Commander для почти всех задач управления файлами.
Но было интересно разработать код для этой особой задачи переименования файлов со всеми ограничениями, которые имеет командный процессор Windows, поскольку он не предназначен для таких задач.
@echo off
setlocal EnableExtensions DisableDelayedExpansion
for /F "eol=| delims=" %%I in ('dir /A-D-H /B 2^>nul ^| %SystemRoot%\System32\findstr.exe /R /C:"19[89][0123456789]" /C:"20[012][0123456789]"') do call :RenameFile "%%I"
endlocal
goto :EOF
:RenameFile
set "FileName=%~n1"
setlocal EnableDelayedExpansion
set "Year=1980"
:YearLoop
set "NewName=!FileName:%Year%=(%Year%)!"
if "!NewName!" == "!FileName!" (
if %Year% == 2029 goto ExitSub
set /A Year+=1
goto YearLoop
)
if "!FileName:(%Year%)=!" == "!FileName!" ren "%~1" "!NewName!%~x1"
:ExitSub
endlocal
goto :EOF
FOR выполняет следующую командную строку в отдельном командном процессе, запущенном в фоновом режиме с cmd.exe /C
:
dir /A-D-H /B 2>nul | C:\Windows\System32\findstr.exe /R /C:"19[89][0123456789]" /C:"20[012][0123456789]"
DIR выводит с использованными параметрами все имена не скрытых файлов в текущем каталоге только с именем файла + расширением и без пути к файлу. Вывод сообщения об ошибке, если в текущем каталоге отсутствует скрытый файл, подавляется путем перенаправления его из дескриптора STDERR на устройство NUL с 2>nul
.
Имена файлов, выводимые с помощью DIR , перенаправляются с помощью |
для обработки STDIN команды FINDSTR , которая выполняет поиск с учетом регистра двумя интерпретированными регулярными выражениями поиска строки из четырех цифр в диапазоне от 1980
до 1999
или в диапазоне от 2000
до 2029
. Проверка не выполняется, если совпадение четырехзначного числа является частью большего числа, такого как 12000 или 19975. И проверка не выполняется, если вокруг четырехзначного числа уже есть круглые скобки.
FINDSTR также интерпретирует ¹
, ²
, ³
как цифру при использовании [0-9]
, что является причиной использования [0123456789]
для реального совпадения только с любым из этих 10-значных символов. Пожалуйста, ознакомьтесь с более подробной информацией о FINDSTR статьях SS64 - FINDSTR и Каковы недокументированные функции и ограничения команды Windows FINDSTR?
FINDSTR выводит все имена файлов, содержащие четыре цифры в диапазоне от 1980
до 2029
для обработки STDOUT процесса фоновой команды.
Пожалуйста, прочитайте статью Microsoft о Использование операторов перенаправления команд для объяснения 2>nul
и |
. Операторы перенаправления >
и |
должны быть экранированы с помощью символа вставки ^
в FOR , чтобы интерпретировать их как буквенные символы, когда интерпретатор команд Windows обрабатывает эту командную строку перед выполнением команды FOR , который выполняет встроенную командную строку dir
в отдельном командном процессе, запущенном в фоновом режиме.
FOR захватывает эти строки и обрабатывает их построчно. По умолчанию для опции eol=
(конец строки) используется точка с запятой, поэтому FOR будет игнорировать все имена файлов, начинающиеся с точки с запятой. По этой причине eol=|
указано, поскольку вертикальная черта не может использоваться в имени файла, и поэтому все захваченные имена файлов обрабатываются с помощью FOR .
FOR будет разделять каждое имя файла по пробелам / табуляциям по умолчанию и назначать только первую подстроку (токен) указанной переменной цикла I
. Это поведение разделения отключается с помощью delims=
, который определяет пустой список разделителей. tokens=*
- это не то же самое, что приводит к удалению начальных пробелов из имен файлов. Имена файлов могут начинаться с одного или нескольких пробелов, хотя это очень необычно.
Имя файла может содержать также восклицательные знаки !
, которые также должны учитываться при использовании отложенного расширения переменной среды. Каждое имя файла передается подпрограмме для дальнейшей обработки.
Цикл используется для замены всех вхождений года, присвоенных переменной цикла Year
, на год в круглых скобках, пока новое имя файла не будет отличаться от имени текущего файла, поскольку подстановка действительно была положительной для искомой строки. for /L %%J in (1980,1,2029) do ...
не использовался, так как этот цикл не может быть завершен, если в имени файла найден правильный год.
После нахождения года в имени файла проверяется, не указан ли этот год в скобках, чтобы избежать переименования файла с именем home vid (1987).mov
на home vid ((1987)).mov
. Так, например, home video 1998.avi
окончательно переименовывается в home video (1998).avi
.
Имя файла, содержащее два числа с четырьмя или более цифрами, также не обрабатывается правильно, так как этот код не может узнать, какой год указан в таком имени файла.
Этот пакетный код не очень быстрый, но он должен работать с перечисленными ограничениями.
Чтобы понять используемые команды и то, как они работают, откройте окно командной строки, выполните там следующие команды и полностью прочитайте все страницы справки, отображаемые для каждой команды.
call /?
dir /?
echo /?
endlocal /?
findstr /?
goto /?
if /?
ren /?
set /?
setlocal /?
См. Также Куда возвращается GOTO: EOF?
PS: Имена файлов с (
или )
в имени делают обработку их с помощью пакетного файла очень часто более сложной, так как в этом случае имя файла всегда должно быть заключено в двойные кавычки, как для имен файлов, содержащих пробел потому что (
и )
также имеют специальное значение для командного процессора Windows cmd.exe
, как это видно из кода выше. См. Также Как интерпретирует сценарии интерпретатора команд Windows (CMD.EXE)?