shell脚本中的模式匹配效率

时间:2016-03-11 14:07:49

标签: performance shell scripting pattern-matching vi

我有一个目录MAIN_DIR,有30个子目录,每个目录包含大约30,000个文件。我想浏览MAIN_DIR中的每个目录,并将匹配某个模式的每个第10个文件复制到另一个位置。这是我的剧本:

cd /path/MAIN_DIR
num=0
for dir in *; do

     cd $dir
     for f in `find . -name \*XYZ*`; do
          if [ `expr $num % 10` -eq 0 ]; then
              cp $f /new/location/new_dir/$f
          fi
          num=$((num+1))
     done
     cd ..

done

它按预期工作,问题是它非常慢,花了大约8个小时来运行所有30个目录。我知道模式匹配和模运算都很慢,但8小时似乎有点高。我有什么办法可以提高这个脚本的速度吗?

2 个答案:

答案 0 :(得分:1)

你的脚本在我的机器上每个30,000个文件目录大约需要1分钟 - 除了选择文件之外不需要复制任何内容。所以我猜你的8个多小时大约30分钟花在选择它们上的效率低下,所以实际问题可能是复制。

您可以用这样的内容替换脚本以确定要复制的文件,但除非您并行复制并且网络/驱动器可以提供该带宽,否则它仍需要7个多小时。

find . -type f -name ... | awk '(FNR%10)==0'

对于所有100万个文件,它在24秒内运行。

答案 1 :(得分:0)

如果你正在使用ashdash,你可能无法改善这一点(我不确定)。

如果你正在使用ksh或bash,请替换

if [ `expr $num % 10` -eq 0 ]; then

if (( $num % 10 )) ; then

这样,您将使用内置于shell中的内部评估,并避免创建子流程。

- 另外,根据上面的评论,我包含了这些示例评估,说明了使用% mod运算符:

 num=9;  if (( $num % 10 )) ; then echo not 10 ; else echo num%10 ; fi
    not a 10
 num=10 ;-if (( $num % 10 )) ; then echo not 10 ; else echo num%10 ; fi
    num%10
 num=20 ;-if (( $num % 10 )) ; then echo not 10 ; else echo num%10 ; fi
    num%10
 num=111;  if (( $num % 10 )) ; then echo not 10 ; else echo num%10 ; fi
    not a 10

我会(为了我自己的信息)将time添加到cp cmd的前面,即

time cp $f /new/location/new_dir/$f

查看要复制的每个文件的个人费用。如果您要通过慢速网络或从驱动器上的某个位置复制到同一驱动器上的另一个位置,那么您可能无法做到这一点来加快速度。

IHTH