Основная проблема заключается в том, что командный процессор Windows cmd.exe
не поддерживает метки внутри командных блоков, которые полностью анализируются перед выполнением команды с использованием командного блока.Пожалуйста, прочтите подробности Как синтаксический анализ сценариев интерпретатора команд Windows (CMD.EXE)?
Решения используют подпрограмму.
@echo off
setlocal EnableExtensions DisableDelayedExpansion
for /L %%N in (0,1,6) do call :ProcessFiles %%N
endlocal
goto :EOF
:ProcessFiles
if not %1 == 0 ( set "SkipOption=skip=%1 " ) else ( set "SkipOption=" )
set "DirVar="
for /F "%SkipOption%eol=| delims=" %%I in (path.txt) do set "DirVar=%%I" & goto GetFileVar
:GetFileVar
set "FileVar="
for /F "%SkipOption%eol=| delims=" %%I in (file.txt) do set "FileVar=%%I" & goto GetDotVar
:GetDotVar
set "DotVar="
for /F "%SkipOption%eol=| delims=" %%I in (dotonefile.txt) do set "DotVar=%%I" & goto CheckFile
:CheckFile
set "DirFile=%DirVar%%FileVar%"
set "DirDotFile=%DirVar%%DotVar%"
if exist "%DirFile%" (
del "%DirDotFile%"
) else (
rename "%DirDotFile%" "%DirFile%"
)
goto :EOF
Более разумный подходиспользовать этот код командного файла вообще без использования текстовых файлов.
@echo off
setlocal EnableExtensions DisableDelayedExpansion
for /F "eol=| delims=" %%I in ('dir "F:\My Pictures\*.1.JPG" /A-D /B /S 2^>nul') do (
for %%J in ("%%~dpnI") do (
if exist "%%~dpnJ%%~xI" (
del "%%I"
) else (
ren "%%I" "%%~nJ%%~xI"
)
)
)
endlocal
Цикл FOR начинается с %ComSpec% /C
еще одного cmd.exe
командного процесса в фоновом режиме для выполнения командыстрока:
dir "F:\My Pictures\*.1.JPG" /A-D /B /S 2>nul
DIR выполняет поиск с указанными параметрами для
- файлов из-за опции
/A-D
(атрибут не каталог) - соответствует регистронезависимому шаблону
*.1.JPG
- в каталоге
F:\My Pictures
и всех его подкаталогах из-за опции /S
- и выводит в голом формате из-заопция
/B
просто - имя файла с расширением файла и полным путем из-за опции
/S
.
DIR выдаст сообщение об ошибке в случаени один файл не может быть найден во всем дереве каталогов, соответствующих этимEria.Это сообщение об ошибке подавляется путем перенаправления его на устройство NUL .
. Прочтите статью Microsoft о Использование операторов перенаправления команд для объяснения 2>nul
.Оператор перенаправления >
должен быть экранирован с помощью символа вставки ^
в командной строке FOR , чтобы интерпретироваться как литеральный символ, когда интерпретатор команд Windows обрабатывает эту командную строку перед выполнением команды FOR , котораявыполняет встроенную командную строку dir
в отдельном командном процессе, запущенном в фоновом режиме.
FOR захватывает все выходные данные для обработки STDOUT запущенного командного процесса и обрабатывает захваченныйтекст построчно после начала cmd.exe
закончено.
FOR игнорирует пустые строки, которые здесь вообще не встречаются. FOR также будет игнорировать строки, начинающиеся с ;
, потому что это опция по умолчанию для конца строки.Поскольку DIR выводит имена файлов с полным путем, невозможно, чтобы строка начиналась с ;
.Но eol=|
, тем не менее, используется для определения вертикальной черты как конца строки, который никогда не может содержать имя папки / файла.
FOR по умолчанию разбивает каждую строку на подстроки (токены)использование нормального пробела и символа горизонтальной табуляции в качестве разделителей.Такое поведение здесь нежелательно, поскольку путь к файлу может содержать символ пробела.По этой причине delims=
используется для определения пустого списка разделителей, который отключает разделение строк.
Внутренний FOR используется для присвоения переменной цикла J
толькострока, оставленная до .1.JPG
.
Условие IF проверяет, существует ли уже файл *.JPG
для текущего файла *.1.JPG
в том же каталоге, что и текущий файл, и в этом случае файл *.1.JPG
удаляется или иным образом переименовывается в *.JPG
, если эта операция удаления или переименования файла вообще разрешена в зависимости от атрибута только для чтения, прав доступа к файлам для текущей учетной записи и текущих прав доступа к файлу.
Нодавайте предположим, что имена файлов изображений могут быть любыми именами файлов, соответствующими *.jpg
, и могут быть не только *.1.jpg
, но также файлы изображений *.2.jpg
до *.99.jpg
, то есть любое число после точки перед расширением файла .jpg
,В этом случае DIR недостаточно для получения списка имен файлов с расширением и полным путем.Дополнительно необходимо использовать FINDSTR с регулярным выражением для фильтрации списка имен файлов.
@echo off
setlocal EnableExtensions DisableDelayedExpansion
for /F "eol=| delims=" %%I in ('dir "F:\My Pictures\*.*.jpg" /A-D /B /S 2^>nul ^| %SystemRoot%\System32\findstr.exe /I /R "\.[0123456789][0123456789]*\.jpg$"') do (
for %%J in ("%%~dpnI") do (
if exist "%%~dpnJ%%~xI" (
del "%%I"
) else (
ren "%%I" "%%~nJ%%~xI"
)
)
)
endlocal
First FINDSTR выводит только строки, прочитанные из STDIN который
- совпадает с учетом регистра из-за опции
/I
- регулярного выражения
\.[0123456789][0123456789]*\.jpg$
- , как явно объявлено с опцией
/R
.
Регулярное выражение соответствует строке, состоящей из точки, одной или нескольких цифр, еще одной точки и строки jpg
, найденной в конце строки.Таким образом, имя файла, например Hello.World.jpg
, выводимое DIR , не соответствует FINDSTR и, следовательно, не выводится FINDSTR и поэтому не обрабатывается FOR .
Но имя файла, например Hello.World.393.jpg
, обрабатывается и либо удаляется, либо переименовывается в Hello.World.jpg
в зависимости от наличия Hello.World.jpg
в том же каталоге.
Для понимания используемых команд и того, как ониработать, открыть окно командной строки, выполнить там следующие команды и полностью прочитать все страницы справки, отображаемые для каждой команды.
call /?
del /?
dir /?
echo /?
endlocal /?
findstr /?
for /?
goto /?
if /?
ren /?
или rename /?
set /?
setlocal /?
См. Также Куда возвращается GOTO: EOF?