我有一个文件放置在不同的文件夹中(文件扩展名为 .mvw)。我想编写一个脚本,该脚本转到每个文件夹并用文件夹名称替换字符串(在文件 *.mvw 中)“D3PLOT_1DForce”。
文件夹结构如下-
- XYZ_DV_L02_P01
- XYZ_DV_L02_P02
- XYZ_DV_L02_P03
我写了以下脚本 -
#!/bin/sh
for ii in XYZ_DV_L02* ; do
(cd "$ii")
find . -iname "*.mvw" -type f -exec sed -i "s/D3PLOT_1DForce_EffPlStrainMax_VonMisesMax/"${ii}"/g" "{}" \;
done
它可以工作并将字符串替换为文件夹的名称,但它会替换所有文件中第一个文件夹的名称。我认为 sed 不会进入 for 循环。
如何让 sed 在循环中工作,以便使用相应的文件夹名称来替换文件中的字符串?
答案1
该cd
命令在子 shell 中执行,因此实际上不执行任何操作。因此,您的find
命令是从父目录执行的,对于 .txt 中的每个子目录名称执行一次XYZ_DV_L02*
。第一次调用sed
会更改所有文件中的字符串,后续调用sed
不会找到该字符串,但无论如何都会执行。
尝试这个:
#!/bin/sh
for ii in XYZ_DV_L02* ; do
find "$ii" -iname "*.mvw" -type f -exec sed -i "
s/D3PLOT_1DForce_EffPlStrainMax_VonMisesMax/${ii}/g" "{}" +
done
感谢 Stéphane Chazelas 的编辑
虽然我只是find
从问题中复制了命令,仅修复了路径,但值得解释一下这些更改:
${ii}
以前没有被引用,现在它是包含整个参数的引号的一部分sed
。- 使用
+
代替\;
将导致对多个文件find
执行一个sed
命令,而不是对每个文件执行一个命令。
编辑
对于评论的请求,这将替换集合中的每个序列[-_a-zA-Z0-9]
,后跟.h3d
替换文本,这是包括.mvw
扩展名的文件名,这就是我理解评论的方式,但它似乎没有用。如果您想访问模式中的文本,可以使用\1
。您可能需要根据您的特定需求调整该套件。
#!/bin/sh
for ii in XYZ_DV_L02* ; do
find "$ii" -iname "*.mvw" -type f -exec sed -i -r "
s/([-_a-zA-Z0-9]+)\.h3d/${ii}.h3d/g" "{}" +
done
答案2
尝试这个,
#!/bin/sh
for ii in XYZ_DV_L02* ; do
cd "$ii"
find . -iname "*.mvw" -type f -exec sed -i "s/D3PLOT_1DForce/"${ii}"/g" "{}" \;
cd ..
done
将目录更改为 for 循环中的第一个输入文件夹并查找文件就可以了。但是在运行下一个循环之前我们必须返回到父目录。
答案3
如果您的目录结构仅包含许多子目录,每个子目录都有.mvw
您想要修改的文件,则无需使用,find
因为您已经确切知道文件所在位置。
for pathname in XYZ_DV_L02*/*.mvw; do
sed -i "s/D3PLOT_1DForce/${pathname%%/*}/g" "$pathname"
done
这将迭代.mvw
指定子目录中的所有文件,并将字符串替换为目录名称。参数扩展会删除中字符串中${pathname%%/*}
第一个之后的所有内容。/
$pathname
测试:
$ tree
.
|-- XYZ_DV_L02_P01
| `-- somefile.mvw
|-- XYZ_DV_L02_P02
| `-- somefile.mvw
`-- XYZ_DV_L02_P03
`-- somefile.mvw
3 directories, 3 files
$ cat XYZ_DV_L02_P0*/*.mvw
Hello D3PLOT_1DForce_EffPlStrainMax_VonMisesMax!
Hello D3PLOT_1DForce_EffPlStrainMax_VonMisesMax!
Hello D3PLOT_1DForce_EffPlStrainMax_VonMisesMax!
(这里运行循环)
$ cat XYZ_DV_L02_P0*/*.mvw
Hello XYZ_DV_L02_P01_EffPlStrainMax_VonMisesMax!
Hello XYZ_DV_L02_P02_EffPlStrainMax_VonMisesMax!
Hello XYZ_DV_L02_P03_EffPlStrainMax_VonMisesMax!
显然,如果您有很深的层次结构,那么您可能无论如何都需要使用,但您可以从内部而不是外部find
进行循环:find
find
find XYZ_DV_L02*/ -type f -name '*.mvw' -exec sh -c '
for pathname do
sed -i "s/D3PLOT_1DForce/${pathname%%/*}/g" "$pathname"
done' sh {} +
在这里,我们找到.mvw
与模式匹配的任何目录下的所有文件XYZ_DV_L02*/
。对于这些找到的文件,我们运行一个循环,该循环执行与本答案开头的循环相同的操作。这会将任何目录下任何位置的D3PLOT_1DForce
所有文件中的字符串替换为相应的目录名称。.mvw
XYZ_DV_L02*
有关的:
这个答案假设 GNUsed
或其他一些实现不使用选项参数sed
进行就地编辑。-i