问题描述
我编写了一个bash函数,将文件名转换为标题大小写,然后将首字母缩写词,相机_DSC / _IMG前缀等大写。这也使连词变为小写。
问题在于它非常慢。我将其运行在1000个文件上作为测试,并且完成了4分40秒。 我有超过一百万个文件要重命名。
该函数从文件中取出一堆sed
替换项,并在初始转换后运行每个替换项以转换所需的大写/小写字母。
这是函数:
(我只能使用BSD / OSX bash,所以${a,}
和sed 's/./\L&/g'
对我不起作用...)
IFS=$'\r\n' GLOBIGnorE='*' command eval 'capsarray=($(cat capslist.txt))'
tc () {
capped="$(echo "$1" | tr [[:upper:]] [[:lower:]] | sed "s^_^_ ^g" | sed "s^/^/ ^g" | awk '{for(i=1;i<=NF;i++){ $i=toupper(substr($i,1,1)) substr($i,2) }}1')"
for d in "${capsarray[@]}"; do
capped2="$(echo "$capped" | sed "s^$d^g")"
capped="$capped2"
done
capped3="$(echo "$capped" | sed "s^_ ^_^g" | sed "s^/ ^/^g")"
echo "$capped3"
}
这是capslist.txt
的一部分:
A ^a
W ^w
With ^with
The ^the
Is ^is
Of ^of
And ^and
Or ^or
But ^but
To ^to
In ^in
By ^by
Dsc^DSC
Img^IMG
_Mg^_MG
\(_[0-9][0-9]\)c^\1C
\(_[0-9][0-9]\)s^\1S
\(_[0-9][0-9]\)a^\1A
_Dji^_DJI
Dji_^DJI_
Img_^IMG_
_Kis\([0-9][0-9]\)^_KIS\1
Dk ^DK
Uk ^UK
Eu ^EU
等...
因此,我将输入文件列表分为16个数组,并在每个部分上同时执行该功能。这使其速度更快,因为现在它可以在多个内核上运行。
现在我在4核(8线程)计算机上的运行时间降至1m30。
但是它仍然不足以处理100万个文件。
这是光荣的多核bash美女:
####### 16 THREADS:
declare -a array1
declare -a array2
declare -a array3
declare -a array4
declare -a array5
declare -a array6
declare -a array7
declare -a array8
declare -a array9
declare -a array10
declare -a array11
declare -a array12
declare -a array13
declare -a array14
declare -a array15
declare -a array16
total=${#inputfiles[@]}
div1="$(expr $total / 16)"
div2="$(expr $div1 + $div1)"
div3="$(expr $div1 + $div1 + $div1)"
div4="$(expr $div1 + $div1 + $div1 + $div1)"
div5="$(expr $div1 + $div1 + $div1 + $div1 + $div1)"
div6="$(expr $div1 + $div1 + $div1 + $div1 + $div1 + $div1)"
div7="$(expr $div1 + $div1 + $div1 + $div1 + $div1 + $div1 + $div1)"
div8="$(expr $div1 + $div1 + $div1 + $div1 + $div1 + $div1 + $div1 + $div1)"
div9="$(expr $div1 + $div1 + $div1 + $div1 + $div1 + $div1 + $div1 + $div1 + $div1)"
div10="$(expr $div1 + $div1 + $div1 + $div1 + $div1 + $div1 + $div1 + $div1 + $div1 + $div1)"
div11="$(expr $div1 + $div1 + $div1 + $div1 + $div1 + $div1 + $div1 + $div1 + $div1 + $div1 + $div1)"
div12="$(expr $div1 + $div1 + $div1 + $div1 + $div1 + $div1 + $div1 + $div1 + $div1 + $div1 + $div1 + $div1)"
div13="$(expr $div1 + $div1 + $div1 + $div1 + $div1 + $div1 + $div1 + $div1 + $div1 + $div1 + $div1 + $div1 + $div1)"
div14="$(expr $div1 + $div1 + $div1 + $div1 + $div1 + $div1 + $div1 + $div1 + $div1 + $div1 + $div1 + $div1 + $div1 + $div1)"
div15="$(expr $div1 + $div1 + $div1 + $div1 + $div1 + $div1 + $div1 + $div1 + $div1 + $div1 + $div1 + $div1 + $div1 + $div1 + $div1)"
array1=("${inputfiles[@]:0:$div1}")
array2=("${inputfiles[@]:$div1:$div1}")
array3=("${inputfiles[@]:$div2:$div1}")
array4=("${inputfiles[@]:$div3:$div1}")
array5=("${inputfiles[@]:$div4:$div1}")
array6=("${inputfiles[@]:$div5:$div1}")
array7=("${inputfiles[@]:$div6:$div1}")
array8=("${inputfiles[@]:$div7:$div1}")
array9=("${inputfiles[@]:$div8:$div1}")
array10=("${inputfiles[@]:$div9:$div1}")
array11=("${inputfiles[@]:$div10:$div1}")
array12=("${inputfiles[@]:$div11:$div1}")
array13=("${inputfiles[@]:$div12:$div1}")
array14=("${inputfiles[@]:$div13:$div1}")
array15=("${inputfiles[@]:$div14:$div1}")
array16=("${inputfiles[@]:$div15}")
function tcmv {
b="$(basename "$d")"
pathtofile="$(dirname "$d")"
mv "$d" "$pathtofile"/"$(tc "$b")"
}
for d in "${array1[@]}"; do tcmv; done &
for d in "${array2[@]}"; do tcmv; done &
for d in "${array3[@]}"; do tcmv; done &
for d in "${array4[@]}"; do tcmv; done &
for d in "${array5[@]}"; do tcmv; done &
for d in "${array6[@]}"; do tcmv; done &
for d in "${array7[@]}"; do tcmv; done &
for d in "${array8[@]}"; do tcmv; done &
for d in "${array9[@]}"; do tcmv; done &
for d in "${array10[@]}"; do tcmv; done &
for d in "${array11[@]}"; do tcmv; done &
for d in "${array12[@]}"; do tcmv; done &
for d in "${array13[@]}"; do tcmv; done &
for d in "${array14[@]}"; do tcmv; done &
for d in "${array15[@]}"; do tcmv; done &
for d in "${array16[@]}"; do tcmv; done &
wait
编辑:带有自定义大小写的示例转换:
20200908_LA_HOLLYWOOD AND HIGHLAND_BUSY STREET_TIME LAPSE_DSC0795.NEF
20200908_LA_Hollywood and Highland_Busy Street_Time Lapse_DSC0795.NEF
^^ ^^^ ^^^ ^^^
20180706_STADIUM_SFO VS NYC_BASKETBALL MATCH_04B8897_OK TO PUBLISH.JPG
20180706_Stadium_SFO vs NYC_Basketball Match_04B8897_OK to Publish.JPG
^^^ ^^ ^^^ ^ ^^ ^^ ^^^
所以我的问题是:
有没有办法使它更快? 又如何?
EDIT2:
根据评论中的建议,我能够提出更好的建议:
IFS=$'\r\n' GLOBIGnorE='*' command eval 'capsarray=($(cat capslist.txt))'
cat tmplist | tr [[:upper:]] [[:lower:]] | sed "s^_^_ ^g" | sed "s^/^/ ^g" | awk '{for(i=1;i<=NF;i++){ $i=toupper(substr($i,2) }}1' > tmplistB
cat tmplist2 | tr [[:upper:]] [[:lower:]] | sed "s^_^_ ^g" | sed "s^/^/ ^g" | awk '{for(i=1;i<=NF;i++){ $i=toupper(substr($i,2) }}1' > tmplist2B
commandvar="sed"
commandvar2="sed"
for d in "${capsarray[@]}"; do
commandvar+=" -e "s^$d^g""
commandvar2+=" -e "s^$d^g""
done
commandvar+=' > tmplistC'
commandvar2+=' > tmplist2C'
cat tmplistB | eval $commandvar
cat tmplist2B | eval $commandvar2
cat tmplistC | sed "s^_ ^_^g" | sed "s^/ ^/^g" > tmplistD
cat tmplist2C | sed "s^_ ^_^g" | sed "s^/ ^/^g" > tmplist2D
IFS=$'\r\n' GLOBIGnorE='*' command eval 'renamedarray=($(cat tmplistD))'
IFS=$'\r\n' GLOBIGnorE='*' command eval 'renameddirarray=($(cat tmplist2D))'
i=0
for d in "${renamedarray[@]}"; do
b="$(basename "$d")"
pathtofile="$(dirname "${myarray[$i]}")"
mv "${myarray[$i]}" "$pathtofile/$b"
i=$((i+1))
done
现在,此操作将对文本文件(而不是实际文件)进行所有艰苦的工作,并使用sed -s
(感谢@ Mark-Setchell nad @thanasisp)
行进速度更快。现在,对于1000个文件,它减少到15秒,而不必将阵列拆分为16个线程。重命名一百万个文件只需要4个多小时!
(它还会先处理文件,然后再处理文件夹,以避免在文件内部重命名之前重命名文件夹)
因此,就我而言,这足以满足我的需要,但我认为我不应该用上述方法回答我的问题,因为我觉得这样可能会更有效率。例如,使用perl和awk解决方案。 (但是我仍然想了解这些内容……继续使用谷歌搜索)
解决方法
暂无找到可以解决该程序问题的有效方法,小编努力寻找整理中!
如果你已经找到好的解决方法,欢迎将解决方案带上本链接一起发送给小编。
小编邮箱:dio#foxmail.com (将#修改为@)