Как получить подстроку со специальным символом при использовании enabledelayedexpansion в CMD? - PullRequest
2 голосов
/ 31 марта 2020

Я хочу переименовать один или несколько файлов, используя cmd. но многие из этих файлов имеют специальный символ. пример:

DCIM_!01.jpeg
DCIM_&01.jpeg
DCIM_=01.jpeg

обычно мы можем использовать это значение «^», чтобы установить особенную строку в качестве простого текста. но когда установлено enabledelayedexpansion, строка не устанавливается

set /p mystring=!

, пользователи определяют строковое значение:!, &, = и другие ...

имя файла определяется другой переменной «FOR» для поиска в папках

поэтому строка «File» имеет значение «DCIM_! 01.jpeg»

Команда для изменения имени файла:

setlocal enabledelayedexpansion
set new_filename=!file:^%mystring%=0!
echo !new_filename!

результаты по запросу:

:=0
file:=0
DCIM_!01.jpeg
DCIM_01.jpeg

Я хочу переписать "!" в «0»:

DCIM_001.jpeg

, когда я не использую специальную строку, команда работает для меня

1 Ответ

1 голос
/ 31 марта 2020

Вот краткий демонстрационный код:

@echo off
setlocal EnableExtensions DisableDelayedExpansion
set "TempDir=%TEMP%\%~n0"
if exist "%TempDir%\" goto CreateFiles
md "%TempDir%" && goto CreateFiles
echo Failed to create temporary directory:
echo/
echo "%TempDir%"
echo/
pause
rem The command endlocal is executed implicit by cmd.
exit /B

:CreateFiles
pushd "%TempDir%"
echo DCIM_!01.jpeg>"%TempDir%\DCIM_!01.jpeg"
echo DCIM_^&02.jpeg>"%TempDir%\DCIM_&02.jpeg"
echo DCIM_=03.jpeg>"%TempDir%\DCIM_=03.jpeg"
echo DCIM_%%04.jpeg>"%TempDir%\DCIM_%%04.jpeg"
echo DCIM_)05.jpeg>"%TempDir%\DCIM_)05.jpeg"

:UserPrompt
set "MyString="
set /P "SearchString=String to replace: "
rem Has the user not entered a string?
if not defined SearchString goto UserPrompt
rem Remove all double quotes.
set "SearchString=%SearchString:"=%"
rem Is there no search string left?
if not defined SearchString goto UserPrompt
rem Replace all exclamation marks by vertical bars.
set "SearchString=%SearchString:!=|%"
echo/

for /F "eol=| delims=" %%I in ('dir "*.jpeg" /A-D /B 2^>nul') do (
    set "RealName=%%I"
    set "FileName=%%I"
    rem Replace in file name all exclamation marks by vertical bars.
    call set "FileName=%%FileName:!=|%%"
    setlocal EnableDelayedExpansion
    set "NewName=!FileName:%SearchString%=0!"
    if not "!NewName!" == "!FileName!" echo ren "!RealName!" "!NewName!"
    endlocal
)

echo/
%SystemRoot%\System32\choice.exe /C NY /N /M "Run once more (Y/N):"
if errorlevel 2 goto UserPrompt

popd
rd /Q /S "%TempDir%"
endlocal

Вы можете видеть, что демонстрационный код не работает для строк поиска, содержащих =. Для замены знаков равенства должен использоваться специальный код, либо используется другой интерпретатор сценария, например PowerShell.
См. Также: Как заменить «=» (знаки равенства) и строковую переменную?

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

Замена ! на | в FOR l oop необходимо сделать ссылку на переменную окружения FileName с помощью %%. Причина в том, что командная строка

call set "FileName=%%FileName:!=|%%"

обрабатывается cmd.exe перед выполнением команды FOR до

call set "FileName=%FileName:!=|%"

Команда CALL используется для принудительного повторного анализа и обработки этой командной строки с помощью cmd.exe на каждой итерации l oop, чтобы действительно заменить символ на текущем строковом значении, присвоенном переменной окружения FileName.

См. Также:

Затем можно включить отложенное расширение, чтобы выполнить замену строки для уже слегка измененного имени файла и выполнить команду REN для имени файла, действительно измененного заменой строки. с реальным именем текущего файла и новым именем файла. Прочитайте этот ответ для получения подробной информации о командах SETLOCAL и ENDLOCAL .

Демонстрационный код не выполняет команду REN , он просто выводит, как REN будет выполнено при удалении команды ECHO .

...