使用输入文件复制文件以读取文件方向

使用输入文件复制文件以读取文件方向

我用来grep搜索 1 TB 的文件。我想要 grep 文件名并将名称放入文本文件中,并且我想要cp与 dir 匹配的所有文件/home/user/matches。我想完成这两项任务,而无需使用 grep 两次搜索所有文件。

我的想法是使用 grep 将文件名输出放入文本文件中

grep -ril "xxx" . >> /home/user/matches/output-filename.txt

现在用作output-filename.txtcp 的输入并使 cp 逐行执行。我怎么做? awk?或者你们有其他想法来避免两次搜索所有文件

答案1

文件路径是除 0 之外的字节序列;它们不一定是文本,更不用说文本行了。特别是文件路径

  • 可能包含换行符
  • 可能包含不形成有效字符的字节序列
  • 可能比 LINE_MAX 长

GNU 实现grep(添加该选项的那个-r)可以以非文本格式打印路径,并且-Z可以安全地进行后处理。例如,GNUxargs可以使用其选项处理该格式-0

xargs -r0 -a <(
  grep -rilZ xxx . |
   tee file.list
)  cp -it /home/user/matches --

(这里也假设 GNUcp作为其-t选项)

如果您想使用 GNU 以人类可以理解的文本格式打印该列表printf

xargs -r0a file.list printf '%q\n'

1 嗯,它应该确保无法解码的字节,因为字符被呈现为$'\234'表示形式。对于包括换行符在内的控制字符也是如此,它被呈现为$'\n'.这解决了上面的前两点,但它不能保证输出的行数会短于LINE_MAX(但话又说回来,标准文本实用程序的 GNU 实现通常对它们支持的行数没有限制)。

答案2

您可以使用find一对链接的exec命令。也许不是最有效的解决方案,因为它grep为每个文件(以及cp每个匹配的文件)调用,但无论文件名中的字符如何,它都会起作用:

mkdir -p ~/matches
find -type f -exec grep -il 'xxx' {} \; -exec cp -p {} ~/matches/ \; > ~/matches/output-filename.txt

答案3

像这样使用tee,xargs命令(用作NULL byte \0文件名分隔符的结尾)和GNU grep

处理带有空格、换行符等的文件名...

mkdir -p ~/matches
grep -Zril "xxx" . |
    tee ~/matches/output-filename.txt |
    xargs -0 -I {} cp {} ~/matches/

相关内容