我已经制作了一个bash函数来分隔大于一定大小的图像文件,但是我有大约20000个文件并且它花费了太多时间并且它根本没有使用CPU,所以我想知道也许没有真正复杂的多处理就可以对它进行一些优化(我不介意多处理,但我不想为这么简单的任务编写20行代码)
这是我的代码:
getpics() {
dir="larger than $1x$2"
mkdir "$dir"
for f in `ls *`; do
a=`file "$f" | grep -Po ", \K[\d]*x[\d]*"`
x=`grep -Po "\d*(?=x)" <<< "$a"`
y=`grep -Po "x\K\d*" <<< "$a"`
echo "$a _______________________ $x, $y"
if [ $x -gt $1 ] && [ $y -gt $2 ] ; then
mv "$f" "$dir/$f"
fi
done
}
答案 0 :(得分:4)
您可以尝试尽可能避免调用外部工具,而是使用bash
内置函数。
例如,要替换所有grep
,您可以使用bash
ERE(适用于Bash 4 +):
re='^.* ([0-9]+)x([0-9]+),.*$'
for f in *; do
desc=$(file "$f")
if [[ $desc =~ $re ]]; then
x=${BASH_REMATCH[1]}
y=${BASH_REMATCH[2]}
# ... check size & move
fi
done
答案 1 :(得分:2)
ls
grep
次呼叫(感谢下面的评论和@ randomir的答案)重构的脚本:
re=', ([0-9]+)x([0-9]+)'
getpics() {
dir="larger than $1x$2"
mkdir "$dir"
for f in *; do
if [[ $(file "$f") =~ $re ]]; then
x=${BASH_REMATCH[1]}
y=${BASH_REMATCH[2]}
echo "$a _______________________ $x, $y"
(( x > $1 && y > $2 )) && mv "$f" "$dir/$f"
fi
done
}
答案 2 :(得分:1)
首先让我们做一些基准测试:
我们从if:
开始$ time for i in `seq 1 100000`; do if [ 2 -gt 1 ] && [ 3 -gt 2 ]; then a=1; fi; done
real 0m0.694s
user 0m0.693s
sys 0m0.003s
$ time for i in `seq 1 100000`; do if [[ 2 -gt 1 && 3 -gt 2 ]]; then a=1; fi; done
real 0m0.428s
user 0m0.424s
sys 0m0.006s
$ time for i in `seq 1 100000`; do if (( 2 > 1 && 3 > 2 )); then a=1; fi; done
real 0m0.366s
user 0m0.364s
sys 0m0.003s
$ time for i in `seq 1 100000`; do (( 2 > 1 && 3 > 2 )) && a=1; done
real 0m0.355s
user 0m0.352s
sys 0m0.005s
现在让我们看一下ls
$ time for i in `ls *`; do a=1; done
real 0m0.280s
user 0m0.249s
sys 0m0.036s
$ time for i in *; do a=1; done
real 0m0.128s
user 0m0.128s
sys 0m0.000s
现在有些人可能想知道是否
desc=$(file "$f")
if [[ $desc =~ $re ]]; then
与
不同if [[ $(file "$f") =~ $re ]]; then
但结果没有区别。我也测试了很多次,但每次都比其他人快。但我不是把结果放在这里,因为我觉得它没用。
你可能想知道
之间是否存在差异 ^.* ([0-9]+)x([0-9]+),.*$
和([0-9]+)x([0-9]+),
但是我测试了它并且没有。但是根据regex101最好的正则表达式(保留分组)是:
.*, ([0-9]+)x([0-9]*) : 33 steps.
, ([0-9]+)x([0-9]+) : 34 steps.
^.* ([0-9]+)x([0-9]+),.*$ : 38 steps.
现在让我们比较获取x
和y
的不同方式:
$ time (files=( * ); for f in "${files[@]:0:1000}"; do IFS=, a=(`file $f`);IFS=x b=(${a[8]});done;)
real 0m5.580s
user 0m1.147s
sys 0m4.498s
$ time (files=( * ); for f in "${files[@]:0:1000}"; do if [[ $(file "$f") =~ $re ]]; then x=${BASH_REMATCH[1]}; y=${BASH_REMATCH[2]}; fi; done)
real 0m5.817s
user 0m1.234s
sys 0m4.619s
$ time (files=( * ); for f in "${files[@]:0:1000}"; do a=(`convert $f -print "%w %h\n" /dev/null`);done;)
real 0m10.356s
user 0m3.624s
sys 0m6.793s
$ time (files=( * ); for f in "${files[@]:0:1000}"; do a=$(file "$f" | grep -Po ", \K\d+x\d+"); IFS=x read x y <<<"$a"; done;)
real 0m12.645s
user 0m2.235s
sys 0m13.914s