Если вы хотите получить чистое пакетное решение, то самым простым способом является инкапсуляция кода в подпрограмму, которая принимает имя файла в качестве аргумента и вызывает эту процедуру из цикла FOR, который выполняет итерацию файла имена. Это общий подход, который можно использовать для любого кода, который вы хотите запустить итеративно против файлов в папке.
Конечный результат вашего кода не создает и не переименовывает никакие папки, поэтому простой FOR безопасен в использовании. Но если ваш код создает или переименовывает папки, цикл FOR также может обрабатывать вновь созданные или переименованные файлы. Это можно решить, используя FOR/F с помощью команды DIR/B.
Примечание - Я удалил из кода мертвые (неиспользуемые) переменные.
@echo off
setlocal enabledelayedexpansion
pushd "c:\path\to\your\folder\containing\files\to\modify"
for %%F in (*.txt) do call :replace "%%F"
exit /b
:replace
set INTEXTFILE=%1
set OUTTEXTFILE=test_out.txt
set SEARCHTEXT=Cat
set REPLACETEXT=Dog
for /f "tokens=1,* delims=¶" %%A in ('"findstr /n ^^ %INTEXTFILE%"') do (
SET string=%%A
for /f "delims=: tokens=1,*" %%a in ("!string!") do set "string=%%b"
if "!string!" == "" (
echo.>>%OUTTEXTFILE%
) else (
SET modified=!string:%SEARCHTEXT%=%REPLACETEXT%!
echo !modified! >> %OUTTEXTFILE%
)
)
del %INTEXTFILE%
rename %OUTTEXTFILE% %INTEXTFILE%
exit /b
Но есть много ограничений и неэффективности с кодом, с большим количеством возможностей для улучшения.
Ограничения:
Входные и выходные линии должны быть немного длиной менее 8191 байт.
Поиск игнорирует случай
Строка поиска не может содержать !
Строка поиска не может начинаться с =
линий, содержащих !
будут повреждены, поскольку задержка расширения активируется, когда %%A
расширяется. Это можно решить путем стратегического включения и выключения задержки внутри цикла (ов).
Ведущий :
будет удален из всех строк, поскольку последовательные символы разделителя рассматриваются как один разделитель.
Замена повреждена, если поисковый запрос содержит %%a
или %%b
или %%A
. Этого можно избежать, передав условия поиска и замены в переменные FOR.
Определенные символы в пределах условий поиска и/или замены могут вызывать проблемы или требовать сложных escape-последовательностей. Это можно упростить, получив желаемые строки в переменных среды (которые могут по-прежнему нуждаться в escape-последовательностях), а затем использовать задержанное расширение и FOR/F для передачи значений в переменные FOR.
Есть неясные ситуации, когда ECHO.
может не работать. Единственный безопасный вариант, который гарантированно работает, - ECHO(
.
Незначительная строка может стать пустой после замены, если строка замены пуста, а пустая строка не будет выводиться должным образом, потому что не было использовано ни ECHO.
, ни ECHO(
.
неэффективностью/другие вопросы
Перенаправление выполняется для каждой строки вывода, который является медленным. Лучше (быстрее) перенаправлять один раз за пределы цикла.
ДЭС/ПЕРЕИМЕНОВАТЬ пару можно заменить одной командой MOVE
ВЫЗОВ является относительно медленным. Лучше всего минимизировать использование CALL, если вы хотите получить самое быстрое решение. Но иногда этого нельзя избежать.
Я предпочитаю, чтобы мое имя файла temp было производным от исходного имени. Я обычно присоединять .new
расширение к оригинальному названию, так «original.txt» становится «original.txt.new»
Ниже высоко оптимизированный код, который обращается ко всем, кроме первых 4 пункта выше. Это примерно так же эффективно и эффективно, как и чистая партия, если вы хотите использовать FOR/F для чтения файла.
@echo off
setlocal disableDelayedExpansion
pushd "c:\path\to\your\folder\containing\files\to\modify"
set "find=Cat"
set "repl=Dog"
setlocal enableDelayedExpansion
for /f delims^=^ eol^= %%S in ("!find!") do (
for /f delims^=^ eol^= %%R in ("!repl!") do (
endlocal
for %%F in (*.txt) do (
for /f "delims=" %%L in ('findstr /n "^" "%%F"') do (
set "ln=%%L"
setlocal enableDelayedExpansion
set "ln=!ln:*:=!"
if defined ln set "ln=!ln:%%S=%%R!"
echo(!ln!
endlocal
)
) >"%%F.new" & move /y "%%F.new" "%%F" >nul
)
)
popd
Для этого требуется большой опыт и знания тайны. Даже после всей работы он все еще имеет следующие ограничения.
Вводные и выходные линии должны быть немного меньше 8191 байта.
Поиск игнорирует случай
Строка поиска не может содержать !
Строка поиска не может начинаться с =
Снятие этих ограничений требует нелепое количество медленно и еще более непроницаемый код. Вряд ли это стоит.
Вот почему я отказался от использования чистой партии для обработки текста, и я разработал JREPL.BAT, чтобы обеспечить мощные возможности текстовой обработки регулярных выражений в среде команд Windows. JREPL - это чистый скрипт (гибридный JScript/пакет), который запускается изначально на любом компьютере Windows с XP.
JREPL делает решение настолько простым, что его можно легко запустить непосредственно в командной строке без какого-либо командного файла.
pushd "c:\your\path\with\files\to\be\modified"
for %F in (*.txt) do call jrepl "Cat" "Dog" /l /f "%F" /o -
popd
Поиск с учетом регистра. Вы можете добавить опцию /i
, если вы хотите, чтобы поиск игнорировал случай. Измените %F
на %%F
, если вы используете команду в пакетном скрипте.
использовать 'FOR' во вложенном то есть' for/f 'delims = "%% # in (' dir/b/s" * mask.txt "') do (for/f" tokens = 1, * delims = ¶ "%% A in ('" findstr/n ^^ %% ~ # "') do (....) ...)' – Paul
Обратите внимание, что ваш внутренний цикл 'for/F' удаляет потенциальные ведущие двоеточия': 'из каждой строки; чтобы избежать этого, используйте '' delims = "', затем 'set 'string = %% a" ', а затем' set' string =! string: *: =! "'; это удаляет номер строки и ** first ** ':', добавленный 'forstring', но ничего больше ... вместо' echo! modified! 'вы должны написать' echo.! modified! ', чтобы избежать' ECHO ' Off', когда полная строка соответствует '! SEARCHTEXT!' И 'REPLACETEXT' пуста ... – aschipfl
@aschipfl: Я предлагаю вам не использовать' echo.! Modified! 'Для этой цели. Вы можете использовать 'echo /! Modified!' Или 'echo (! Modified!'. Дополнительная информация в [этот пост] (http://www.dostips.com/forum/viewtopic.php?f=3&t=774). – Aacini