У меня есть такое дерево каталогов

c:\work\src\A\D1\foo.txt
c:\work\src\A\D2\foo.txt
c:\work\src\B\foo.txt

Я хочу запустить редактор потоков (sed) для каждого файла foo.txt и заменить текст на sed. Место назначения будет выглядеть так:

c:\work\dst\A\D1\foo.txt
c:\work\dst\A\D2\foo.txt
c:\work\dst\B\foo.txt

Я попытался найти все foot.txt с помощью команды for командного процессора Windows, но я не знаю, как получить часть из базовой директории:

cd c:\work\src
FOR /R %d in (sources) DO sed %d > c:\work\dst\%d

Это не работает, так как% d расширяется до c:\work\src\A\D1\foo.txt вместо A\D1\foo.txt .

Как я могу перебрать все файлы и правильно построить целевой путь?

редактировать

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

set dst=c:\work\dst\
del /f foo.tmp
FOR /R %%d in (.) DO @echo %%d >> foo.tmp
sed s/C:\\work\\src\\// foo.tmp > bah.tmp
FOR /F IN (bah.tmp) DO sed -f patch.sed %%i > %dst%\%%i
del foo.tmp bah.tmp

У этого подхода есть недостаток, заключающийся в том, что текущий каталог не может быть получен из %CD% но должен быть жестко запрограммирован, так как sed требует экранированной обратной косой черты. Далее я должен бороться с временными файлами тоже. Есть ли более элегантный способ, как

FOR /R "c:\work\src" /D %%d IN (foo.txt) DO @if exist %%d  sed ????

2 ответа2

0

ОК, я установил тот же набор тестовых файлов:

X:\>dir /s /b
X:\work
X:\work\src
X:\work\src\A
X:\work\src\B
X:\work\src\A\D1
X:\work\src\A\D2
X:\work\src\A\D1\foo.txt
X:\work\src\A\D2\foo.txt
X:\work\src\B\foo.txt

Затем у меня есть пакетный файл. Допустим, он сохранен как: "D:\batchscript.cmd":

@echo off

rem get the "unique" part of the source and dest paths: "\src\", "\dst\"
set "zusource=\src\"
set "zudest=\dst\"



rem From within the current directory, and all subdirectories,
rem process each file named "foo.txt"
for /f "usebackq delims=" %%f in (`dir /s /b "foo.txt"`) do call :work "%%~f"

rem We are done. Go "exit" the script.
goto :EOF



:work
rem get the full name of the current "source" file: "X:\work\src\A\D1\foo.txt"
set "zsourcefq=%~1"



rem substitute the "unique" parts:
rem get "X:\work\dst\A\D1\foo.txt" from "X:\work\src\A\D1\foo.txt"
for /f "usebackq delims=" %%g in (`echo set "zdestfq=%%zsourcefq:%zusource%=%zudest%%%"`) do %%g



rem make the destination directory if necessaary: "X:\work\dst\A\D1"
rem two ways, first relies on your specific file "name", second is "universal"

rem md "%zdestfq:foo.txt=%" 2>nul
for %%g in ("%zdestfq%") do md "%%~dpg" 2>nul



echo Processing: "%zsourcefq%" --^> "%zdestfq%"

rem do your "sed" command here
echo     sed -r "s/whatever/whateverelse/g" "%zsourcefq%" ^> "%zdestfq%"

goto :EOF

Чтобы использовать scirpt, сначала перейдите в каталог "source":

X:\>CD /D "X:\work\src"
X:\work\src>

Затем запустите скрипт:

X:\work\src>"D:\batchscript.cmd"
Processing: "X:\work\src\A\D1\foo.txt" --> "X:\work\dst\A\D1\foo.txt"
    sed -r "s/whatever/whateverelse/g" "X:\work\src\A\D1\foo.txt" > "X:\work\dst\A\D1\foo.txt"
Processing: "X:\work\src\A\D2\foo.txt" --> "X:\work\dst\A\D2\foo.txt"
    sed -r "s/whatever/whateverelse/g" "X:\work\src\A\D2\foo.txt" > "X:\work\dst\A\D2\foo.txt"
Processing: "X:\work\src\B\foo.txt" --> "X:\work\dst\B\foo.txt"
    sed -r "s/whatever/whateverelse/g" "X:\work\src\B\foo.txt" > "X:\work\dst\B\foo.txt"

Измените строку, которая начинается: "echo sed -r..." на любую нужную команду sed.

0

Та же концепция, что и сценарий Кевина. Просто чуть короче. :-)

@echo off
::Get the directory from whence the script was called
set CWD=%~dp0
set CWD
for /R %%g in (foo.txt) do (if exist "%%g" call :GetPath "%%g")
goto :exit  

:GetPath
if not exist "%~1" goto :EOF
echo Original: %~1
set _nfile=%~1
call set _nfile=%%_nfile:%CWD%=%%
echo NFile: %_nfile%
goto :EOF

:exit
set CWD=
set _nfile=

Добавьте вашу команду SED в процедуру GetPath и передайте переменную _nfile .

Всё ещё ищете ответ? Посмотрите другие вопросы с метками .