基于这个脚本:
find . -name "*.txt" | grep 'LINUX/UNIX'
和
find . -name "*.txt" | grep 'LINUX/UNIX' | xargs cp <to a path>
从这里 ,我可以 grep 文件查找某个字符串,然后将其复制到一个目录中(如果它们包含该字符串),然后将它们保留为单独的文件。如何将这些文件整理成一个连贯的文档?
示例 我的想法如下:我有一个引文存档,分布在数百个文件夹中的单独文件中,文件夹的名称是各自的主题。所以“philosophy/ontology/concepts/aletheia/notes.tex”将包含我关于aletheia等哲学概念的所有笔记。
它们都遵循某种命名约定(名称始终是:notes.tex),因此 grep 它们很容易。我可以通过 grep 搜索它们,但我希望能够有一个脚本,不仅可以找到它们,而且还可以将包含相应字符串的所有文件连接到一个大文件中。
答案1
选择*.txt
当前目录或以下目录中名称匹配的常规文件,其中包含特定的细绳(不包含特定正则表达式的匹配项),并且要将这些文件按照找到的顺序连接在一起,您可以使用
find . -name '*.txt' -type f -exec grep -q -F 'LINUX/UNIX' {} \; -exec cat {} + >myfile
或者
find . -name '*.txt' -type f -exec sh -c '
for pathname do
grep -q -F "LINUX/UNIX" "$pathname" && cat "$pathname"
done' sh {} + >myfile
grep
此处使用该实用程序及其-q
选项。这使得它不输出任何内容,但一旦给定的模式匹配,它就会以零退出状态终止,表示“成功”。我们在上面的两个命令中使用此退出状态作为测试,以仅选择那些包含字符串 的文件LINUX/UNIX
。
使其-F
将grep
模式解释为细绳而不是作为正则表达式。这可能会使命令更快一点,但也意味着您不必担心搜索字符串,而*this*
无需*
特殊处理字符(因为它在正则表达式中很特殊)。
这两个命令都将串联的文件数据写入名为myfile
.如果该文件已经存在,它将被截断(清空),否则将创建它。我故意选择了一个输出文件名不是可以通过命令找到find
,即不以 . 结尾的命令.txt
。
请注意,该问题当前包含的代码似乎过滤了find
with的输出grep
,然后调用cp
via xargs
。这不是问题的用户自己的代码,它有几个问题。一个问题是它不会连接任何文件的内容,另一个问题是它将 应用于grep
输出的路径名find
而不是文件的内容。也可以看看为什么循环查找的输出是不好的做法?这是相关的。
使用问题中代码的格式来实际解决问题这问题,即让find
生成路径名列表,然后分别选择grep
我们感兴趣的路径名,最后cat
是:
find . -name '*.txt' -type f -print0 |
xargs -0 grep -lZ -F 'LINUX/UNIX' |
xargs -0 cat >myfile
.txt
这会将名称以from结尾的文件的路径名列表传递find
到第一个xargs
作为 nul 分隔列表。该xargs
实用程序调用grep
这些,并grep
输出包含匹配项的文件的路径名,同样作为空分隔列表。这使得它-l
输出匹配文件的路径名,并将-Z
其转换为空分隔列表而不是换行分隔列表。
然后,该列表由在每个文件上xargs
调用的最终函数读取。像以前一样cat
写入连接结果。myfile
请注意,这是解决问题的一种更尴尬的方法,有可能忘记管道阶段之间文件列表的格式,并假设运行代码的人必须使用 GNU 系统,或者至少是 GNU 工具(即它是不可移植的)。