2

我正在尝试递归查找与 *.xml 模式匹配的所有文件并删除其中的一些代码。

这就是我想出的:

  • 查找所有 .xml 文件并删除行
  • 从第一次出现def=something到第一次出现</box>

find config/view -type f -name "*.xml" -exec sed -n '/def=something/,/<\/box>/!p' > tmp.xml {} \; -exec mv tmp.xml {} \;

它适用于目录中的 1 个文件,但它提供:

mv: cannot access tmp.xml

当我在包含许多文件的目录上调用它时

我的脚本中的错误在哪里?或者也许有更好/更简单的方法来做到这一点?

4

2 回答 2

2

>是壳结构,不能与-exec主结构一起使用;它的参数直接传递给exec系列中的系统调用之一,而不是由 shell 处理。find>andtmp.xml视为传递给的另外两个字符串参数sed,而不是重定向,因此tmp.xml永远不会创建。

一种选择是为每个文件显式启动一个 shell:

find config/view -type f -name "*.xml" -exec \
  sh -c "sed -in '/def=something/,/<\/box>/!p' {} > tmp.xml && mv tmp.xml {}"

另一个,正如 fedorqui 所建议的,是让sed使用选项来处理原子文件操作本身-i(请注意,-i不同实现之间的使用略有不同;请查看您的sed手册页以获取详细信息)。

于 2013-07-03T14:56:15.740 回答
2

错误是在 的-exec sed语句中find,您没有执行:

sed -n '/def=something/,/</box>/!p' > tmp.xml {}

(带有重定向)。

实际上,您的行相当于:

find config/view -type f -name "*.xml" -exec sed -n '/def=something/,/<\/box>/!p' {} \; -exec mv tmp.xml {} \; > tmp.xml

也就是说,它的所有输出都find被重定向到文件tmp.xml。然后,在找到第一个文件后,tmp.xml 不再存在(因为它已被移动),一切都搞砸了!

要解决此问题,您可以使用内联编辑,如 fedorqui 的回答所示:

find config/view -type f -name "*.xml" -exec sed -i -n '/def=something/,/<\/box>/!p' {} +

(注意+行尾的),或者您可以:

find config/view -type f -name "*.xml" -exec bash -c 'sed -n "/def=something/,/<\/box>/!p" "$0" > tmp.xml; mv tmp.xml "$0"' {} \;

但这不是很好。不过,它很有用,以防您sed不支持该-i标志(GNU支持sed)。

于 2013-07-03T14:59:06.857 回答