我需要使用具有特定名称模式的几个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 很困惑,因为我没有正确指定每个命令的结束位置,但我不知道如何正确完成。
-exec
接受一个简单的命令及其参数;它根本不处理管道或重定向等shell结构。您的原始命令与
find . -name '*dna.toplevel.txt.gz' -exec zcat {} ; >> all.txt
因为 shell 会立即识别输出重定向,并在识别命令 (find
) 及其参数之前将其从命令行中删除。
由于sed
需要 find
中的文件名作为其命令的一部分,因此您需要运行一个 shell,该 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
不包含任何|
字符;如果是这样,则需要选择其他分隔符。
尝试在参数周围加上引号 (
"
) 以-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 ;