我有一个像这样的目录树
c:\work\src\A\D1\foo.txt
c:\work\src\A\D2\foo.txt
c:\work\src\B\foo.txt
我想为每个 foo.txt 运行流编辑器 (sed),并用 sed 替换一些文本。目标将如下所示:
c:\work\dst\A\D1\foo.txt
c:\work\dst\A\D2\foo.txt
c:\work\dst\B\foo.txt
我尝试使用 Windows 命令处理器的 for 命令查找所有 foot.txt,但我不知道如何从基目录中获取该部分:
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 ????
答案1
与 Kevin 的剧本概念相同。只是稍微短一点。:-)
@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=
在“GetPath”例程中添加 SED 命令并传递_nfile
变量。
答案2
好的,我设置了同一组测试文件:
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
要使用该脚本,首先更改到“源”目录:
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 命令。