我需要在多个文件中搜索一个模式并获取最新文件以进行进一步处理。我试图在 shell 脚本中执行此操作。我尝试按如下方式执行
file=`grep -lh <pattern> <file_name> | tail -1`
但是 grep 列出的文件是 als
而不是ls -lrt
。我尝试了以下命令
ls -lrt `grep -l <pattern> <file name>`
但我无法将此命令合并到 shell 脚本中。如能提供任何帮助,我将不胜感激。
谢谢
答案1
这是很多更快。而其他答案grep
全部文件,它会首先搜索最新的文件,一旦找到模式就停止。
此行代码将结果捕获到一个变量中:
file=$(while read file; do grep pattern "$file" >/dev/null;[[ $? ]]; then echo "$file"; break; fi; done < <(find $startdir -maxdepth 1 -type f -printf "%T@:%p\n"|sort -nr|cut -d: -f2-))
这是一个更易于阅读的 Bash 脚本版本:
#!/bin/bash
while read file
do
grep pattern "$file" > /dev/null
if [[ $? ]]
then
echo "$file"
break
fi
done < <(find $startdir -maxdepth 1 -type f -printf "%T@:%p\n" |
sort -nr |
cut -d: -f2-)
答案2
您可以将 grep 的输出通过管道传输到 xargs,以便在通过 tail 管道传输之前使用 ls -lrt
答案3
这应该可以做到:
ls -lrt|awk '{print $9}'|xargs -n1 grep <string>|tail -n1|awk '{print $1}'
您可能需要更改 awk 中打印的变量,这取决于您对 ls 和 grep 的实现。
基本上,先对文件进行排序,然后查找字符串,然后取最后的结果。
答案4
在您的第一个示例中,grep
不应重新排序您传递给它的文件名。如果您明确传递它们,它将按照您传递给它的文件列表的顺序打印输出。但是,如果您传递通配符,那么您的 shell 将按词汇顺序扩展该通配符是正确的(ls
正如您所指出的,这基本上是默认顺序)。
在查看了其他建议后,我提出以下建议:
file=`ls -t --quoting-style=shell "dir" | xargs grep -l "regex" | head -n 1`
我认为这可以满足您的要求,并且解决了其他人提出的问题,如下所示:
- 您可以使用
ls -t
without-l
,因此无需解析ls -l
with的输出awk
或cut
仅获取文件名。 - 不要反转 的排序顺序
ls
。使用ls -t
将最新的文件放在第一位,并且head
一旦找到第一个匹配的文件,就会使用 抓取第一个文件会使管道短路(因此您会搜索找到匹配项所需的最少文件列表)。 - 通过管道
xargs
有效地搜索无限数量的文件,而不会遇到最大命令行长度,并且无需循环。 - 根据需要使用
ls --quoting-style=shell
带有单引号的引号文件名,以便正确处理嵌入空格或控制字符的文件名。
请注意,这--quoting-style
是 GNU 扩展,不太可能与非 GNU 一起使用ls
。在 Linux 上应该没问题。下面的代码更易于移植,但添加了对sed
引用文件名的调用,因此开销会稍微大一些:
file=`ls -t "dir" | sed 's/\(.*\)/"\1"/' | xargs grep -l "regex" | head -n 1`