我有一个要导航的大目录。我正在寻找与特定模式匹配的文件名。为此,我使用find命令。
还有一个与我的模式匹配的文件名子集,其中包含我感兴趣的子字符串。我希望首先打印这些文件,同时还要按字母顺序对所有输出进行排序(就像值是分区,然后对两个分区分别进行排序,或者好像对输出进行了排序,然后将其稳定地分区)。
我正在运行Ubuntu 18.04.1 LTS。
到目前为止,我仅尝试对输出进行排序,并对其进行grepping处理以过滤出包含要搜索的子字符串的文件名。不必这样做会更好(目录很大,搜索两次有点慢)。
find . <...more stuff comes here...> | sort | grep <substring>
find . <...more stuff comes here...> | sort | grep -v <substring>
尽管如此,我还是要做以下事情:
find . <...more stuff comes here...> | sort > tempfile
tempfile > grep <substring>
tempfile > grep -v <substring>
rm tempfile
这是更快的方法,但是这样我仍然必须两次遍历列表,并在两次之间做额外的文件IO,这很浪费。
(顺便说一句,我不允许显示模式或子字符串。)
简而言之:我想查看分区结果,而不必过滤两次。
编辑:一个例子是:
find | sort
命令的输出:
./aaaaaafoo
./bbbbbbfoo
./ccccccbar
./ddddddbar
./eeeeeefoo
./ffffffbaz
./ggggggfoobar
./hhhhhhbar
使用子字符串'foo'
,我希望输出为:
./aaaaaafoo
./bbbbbbfoo
./eeeeeefoo
./ggggggfoobar
./ccccccbar
./ddddddbar
./ffffffbaz
./hhhhhhbar
答案 0 :(得分:1)
最佳方法取决于瓶颈所在(可能是I / O的速度),因此您将需要根据实际数据对所有建议的方法进行基准测试。为了给您一个想法,我对一个2GB的Word文件进行了一个简单的测试,读写nvme存储:
$ time ( grep 'ab*ad' <words2 >a1; grep -v 'ab*ad' <words2 >a2 )
real 0m12.226s
user 0m9.733s
sys 0m1.784s
$ time awk <words2 '(/ab*ad/){print >"a1";next}{print}'>a2
real 0m35.864s
user 0m33.473s
sys 0m1.680s
$ time perl -ne '/ab*ad/ ? print STDOUT : print STDERR' <words2 >a1 2>a2
real 4m40.959s
user 1m8.288s
sys 3m32.057s
$ time ( while read -r line; do [[ $line =~ ab*ad ]] && echo "$line" || echo 1>&2 "$line"; done ) <words2 >a1 2>a2
^C # aborted the run as it was so slow
这两个grep方法,我们可能会认为效率低下,但实际上并非如此。如果I / O可能成为瓶颈,则可能需要进行一些调整:
find . <...more stuff comes here...> | sort | gzip -1c >tempfile
zcat tempfile | grep <substring>
zcat tempfile | grep -v <substring>
rm tempfile`
这对我的配置没有帮助:
$time ( gzip -1c <words2 >wz; zcat wz |\
fgrep 'abad' >a1; zcat wz | fgrep -v 'abad' >a2 )
real 0m59.072s
user 1m6.804s
sys 0m3.609s
$ ls -la words2 wz
-rw-rw-r-- 1 jhnc jhnc 1989791744 Feb 8 23:40 words2
-rw-rw-r-- 1 jhnc jhnc 661174851 Feb 9 00:11 wz
但是请注意,数据文件的大小只有三分之一,这对于慢速存储可能是有利的。
最后一点:如果数据文件很大,我怀疑排序将是过程中最慢的部分。
答案 1 :(得分:0)
我的解决方案:
rm -f a.txt # needed because of >> operator
find . <...more stuff comes here...> | sort |
awk ' /substring/ { print >>"a.txt"; next } {print}' >b.txt
注1:/substring/
是一个正则表达式
注意2:您还可以重定向到例如/dev/fd/5
或在awk中使用print | "command ....
。参见man awk
。