在find -exec中使用zcat和sed

时间:2016-07-07 14:12:05

标签: bash sed find zcat

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

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

它运作得很好。问题是,现在我需要动态编辑文本以替换特定字符“>”使用“> filename |”。我已经成功做到了这一点:

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

但我收到以下错误:

  • sed:无法读取;:没有此类文件或目录
  • 找到:缺少`-exec'
  • 的参数

我理解可怜的bash很困惑,因为我没有正确指定每个命令的结束位置,但我不知道如何正确执行。

2 个答案:

答案 0 :(得分:1)

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

相同
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不包含任何|个字符;如果是这样,您需要选择不同的分隔符。

答案 1 :(得分:-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 \;