稳定的分区外壳程序输出

时间:2019-02-08 23:05:08

标签: bash shell

我有一个要导航的大目录。我正在寻找与特定模式匹配的文件名。为此,我使用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

2 个答案:

答案 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