【问题标题】:Remove part of an .xml file in console在控制台中删除部分 .xml 文件
【发布时间】:2013-07-01 07:59:29
【问题描述】:

我正在尝试递归查找与 *.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

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

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

【问题讨论】:

    标签: xml bash replace sed console


    【解决方案1】:

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

    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 支持)。

    【讨论】:

    • btw -in 不好,文件中的行加倍,选项应该是 -i -n
    【解决方案2】:

    &gt; 是一个 shell 结构,不能与 -exec 主节点一起使用;它的参数直接传递给exec 系列中的系统调用之一,而不由shell 处理。 find&gt;tmp.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 手册页以获取详细信息)。

    【讨论】:

    • {} 不能这样用!
    • @gniourf_gniourf 是的,我看到我正在添加 {},因为 > 之后出现错误,没有 {} 它挂起
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2022-01-23
    • 1970-01-01
    • 1970-01-01
    • 2012-06-01
    • 2021-07-07
    相关资源
    最近更新 更多