【问题标题】:How to use the name of the file with sed in a find expression如何在查找表达式中使用带有 sed 的文件名
【发布时间】:2013-10-25 01:10:34
【问题描述】:

试图回答Using Bash/Perl to modify files based on each file's name 以我不知道如何同时使用findsed 的方式结束。

假设有一个特定的文件结构,我们要在其中更改一行,并附加文件名。

如果它是一个普通的for 循环,我们会这样做:

for file in dir/*
do
   sed -i "s/text/text plus $file/g" $file
done

但是假设我们想使用find 来更改所有子目录中的文件。在这种情况下,我会使用...

find . -type f -exec sed -i "s/text/text plus {}/g" {} \;
                                              ^
                                   it does not like this part

但是sed 中的这些{} 不被接受,我得到了错误

sed: -e expression #1, char 20: `s' 的未知选项

我发现了一些类似的问题 (1),但无法概括到足以让我在这种情况下理解它。

我相信你们会为此提供一个很好的解决方案。谢谢!

【问题讨论】:

    标签: bash sed find exec


    【解决方案1】:

    我真的认为问题在于您的文件名包含 /,这就是 sed 认为它启动选项字符串的原因。

    在您的 sed 命令中将 / 替换为 @ 即可。

    我在 Linux BASH 上试了一下,效果很好

    find . -type f -exec sed -i -e "s@text@test plus {}@g" {} \;
    

    【讨论】:

    • 谢谢@Laurent,我没注意到!你的回答很有帮助。我终于尝试使用 basename 使其工作,如对 devnull 答案的评论中所示。如果您看到这样做的方法,那也将非常受欢迎:)
    【解决方案2】:

    find 将返回 pathnames(相对或绝对),具体取决于您指定的路径。

    这会与您指定的分隔符冲突,即/。更改sed 的分隔符,您应该会很好:

    find . -type f -exec sed -i "s|text|text plus {}|g" {} \;
    

    编辑:要从路径中删除前导 ./,您可以尝试:

    find . -type f -exec sh -c '$f={}; f=${f/.\//}; sed -i "s|text|text plus ${f}|g" {}' \;
    

    我确信可能存在更好的解决方案......

    【讨论】:

    • 哦,这很聪明@devnull。我认为这是sed 本身的问题。谢谢你的好解释。用$(basename {}) 替换{} 我仍然得到./。有什么办法可以删除这部分?
    • 就是这样,谢谢!由于最终的解决方案与我来自stackoverflow.com/q/17788236/1983854 的最初问题中所需的解决方案非常相似,因此我建议您和 Laurent 回答这个问题,因为我这样做有点复制您的答案。
    猜你喜欢
    • 2019-04-02
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2016-06-26
    • 1970-01-01
    • 2020-04-22
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多