Bash - 在文件列表中搜索选择性文件



我有一个n个文件的列表,除了数字(例如file_1,file_2,file_3...file_n)之外,它们都具有相同的名称。 然而,我感兴趣的并不是所有这些文件,只是一些,因为只有一些具有我需要的分子结构。 但是,在这组 n 个文件中,我不知道哪些文件具有必要的结构(注意,每个文件只有一个结构)。

确定哪个文件具有我需要的结构的最佳方法是什么?我只需要识别它们。 我想过制作两个向量,一个是所有文件的名称,另一个是标识分子的单词(文件中的单词可以使用 grep 命令找到)。

我想用这两个向量创建两个循环,但是,我在这次尝试中发现了问题。

L='1 2 3 4 5 6 n'
M='molecule1 molecule2 molecule3...'
for l in $L
do
for m in $M
do
echo "$l" >> files.gjf
grep "$m" file_$l.gjf >> files.gjf
done
done

这两个循环的问题在于我有一组非常大的文件和分子,所以我用来识别我需要的文件的 echo 命令使我的输出非常大。我用 500 个文件向量和只有 51 个分子执行的测试生成了 24013 行的输出 (files.gjf)。

我可以使用其他代码以更可靠的方式执行此操作吗?

grep可以一次性查找多个字符串,-l并且一旦在每个文件中找到第一个字符串,就可以停止搜索,并将该文件报告为匹配项。 所以也许你只是在寻找

grep -l -E 'molecule1|molecule2|molecule3|.....' file_1.gjf file_2.gjf file_3.gjf ... >files.gjf

如果您只想搜索与通配符file_*.gjf匹配的所有文件,那么这是一个明显且简单的简化。

这不会让您看到确切找到的搜索字符串,尽管只需删除-l即可解决此问题(但随后生成更多输出并在每次匹配之前打印出带有文件名的所有匹配项;因此,如果有很多匹配项,则可能比原始尝试更多的输出)。

我使用-E选项来启用不同的模式语法,这样可以更轻松地在一个模式中指定多个搜索字符串。您可能还想研究一下允许您将模式放在文件中-f(也许-F将每个模式视为文本字符串而不是正则表达式)。

printf '%sn' molecule1 molecule2 molecule3 ... |
grep -Ff - -l file_*.gjf >files.gjf

在这里,我们在标准输入上提供模式"file"(在许多Unix命令中通常用伪文件名-表示),而不是将它们存储在物理文件中。 也许单独运行printf部分以查看它产生什么。

顺便说一句,通过在最终done之后移动重定向,可以使您的嵌套循环更有效。主循环中的每个>>都将打开文件进行写入,并在每次迭代中寻求到最后。这在现代计算机上是一个相当快的操作,但仍然没有必要。

for thing in list of things; do  # really no point in using a variable
for other in more stuff; do
echo "$thing"
grep "$other" "file_$thing"
done
done >result

将外部循环的所有标准输出收集到单个重定向中,该重定向只需打开文件一次(并避免了稍微讨厌的追加操作,如果要覆盖上次运行的结果,则需要单独清除文件)。

我会这样构建它。 我会使用数组来存储您正在寻找的关键字。

declare -a a_keywords 
a_keywords="word1 word2 etc" 

然后我会遍历该数组中的元素:

for (( i = 0 ; i < ${#a_keywords[@]} ; i++ )) ; do 

然后对每个结果执行 grep:

grep -r "${a_keywords[i]}" /path/to/root/folder/for/your/files/ 

关闭您的 for 循环(带done)。

如果你使用上面的结构来加载一个数组(declare -a a_keywordsResults),那么你grep "${a_keywordsResults[@]}"在类似的for循环中使用你的数字数组(declare -a a_keyNumbs)。

你可以反转这个结构(首先是麻木的grep,然后是单词结果的grep),但这取决于哪种可能更适合你的具体情况。

如果您需要最终结果的输出(通过两个 greps 的结果),您可以在上述所有内容之后将剩余的内容传递到文件中。

如果我误解了你的目的,请告诉我。

最新更新