【问题标题】:Using zcat and sed in find -exec在 find -exec 中使用 zcat 和 sed
【发布时间】:2016-11-09 21:42:50
【问题描述】:

我需要使用几个具有特定名称模式的 gzip 压缩文件的内容创建一个大文本文件。为此,我使用了:

find . -name '*dna.toplevel.txt.gz' -exec zcat {} >> all.txt \;

它工作得很好。问题是,现在我需要动态编辑文本以用“文件名|”替换特定字符“>”。我已经成功地做了这个:

find . -name '*dna.toplevel.txt.gz' -exec zcat {} | sed 's/>/>{}|/g' >> all.txt \;

但我收到以下错误:

  • sed: 无法读取 ;: 没有这样的文件或目录
  • 发现:`-exec' 缺少参数

我知道糟糕的 bash 很困惑,因为我没有正确指定每个命令的结束位置,但我不知道如何正确地做。

【问题讨论】:

    标签: bash sed find zcat


    【解决方案1】:

    尝试在 -exec 的参数周围加上引号 (")。

    find . -name '*dna.toplevel.txt.gz' -exec "zcat {} | sed 's/>/>{}|/g'" >> all.txt \;
    

    你需要逃离管道:

    find . -name '*dna.toplevel.txt.gz' -exec zcat {} \| sed 's/>/>{}|/g' >> all.txt \;
    

    【讨论】:

    • 谢谢,不幸的是,这导致了以下错误:bash: /: Is a directoryfind: missing argument to `-exec'
    【解决方案2】:

    -exec 接受一个简单的命令及其参数;它根本不处理管道或重定向等外壳结构。您的原始命令与

    相同
    find . -name '*dna.toplevel.txt.gz' -exec zcat {} \; >> all.txt
    

    因为 shell 会立即识别输出重定向并在识别命令 (find) 及其参数之前将其从命令行中删除。

    由于sed 需要来自find 的文件名作为其命令的一部分,因此您需要运行一个shell,通过-c 选项将管道作为参数。

    find . -name '*dna.toplevel.txt.gz' -exec \
      sh -c "zcat {} | sed 's/>/>{}|/g'" \; >> all.txt
    

    这种方法存在一些问题;修复它们需要使sh 命令更加复杂。如果您使用的是bash 4 或更高版本,我建议您完全放弃find 并使用shell 循环和** glob:

    shopt -s globstar
    for f in ./**/*dna.toplevel.txt.gz; do
        zcat "$f" | sed "s|>|>$f|g"
    done >> all.txt
    

    如果此命令正在创建all.txt,您可以简单地使用> 而不是>>。这也假设$f 不会包含任何| 字符;如果是这样,您将需要选择不同的分隔符。

    【讨论】:

    • 谢谢,我想我会用这个方法。
    猜你喜欢
    • 2019-04-09
    • 2017-08-08
    • 2019-02-19
    • 2015-09-08
    • 2018-10-09
    • 2011-11-30
    • 2020-05-27
    • 1970-01-01
    相关资源
    最近更新 更多