xargs 常见于批处理, 下面举个例子:将一个目录中的mp3
文件改为pcm
后缀名,下面的方法从错误一步步的改进并分析
ls *.mp3|xargs -n1 -I{} mv {} $(basename {} .mp3).pcm
xyz@localhost ~/test $
:>lmy.mp3
xyz@localhost ~/test $ls lmy.mp3|xargs -n1 -I{} mv {} $(basename {}.mp3).pcm
xyz@localhost ~/test $ll
total 0
-rw-r–r–. 1 xyz xyz 0 Jul 2 18:45lmy.mp3.pcm
does't work.
原因: shell 最先执行子命令$(basename {} .mp3)
, 所以{}不会被替换. 它在一个新的进程中将执行的结果返回就是{}
, 所以最初的命令变为mv {} {}.pcm
这时候进行{}的替换, 所以结果是lmy.mp3.pcm
ls *.mp3|xargs -n1 -I{} sh -c 'mv {} $(basename {} .mp3).pcm'
xyz@localhost ~/test $
:>lmy.mp3
xyz@localhost ~/test $ls *.mp3|xargs -n1 -I{} sh -c 'mv {} $(basename {} .mp3).pcm'
xyz@localhost ~/test $ll
total 0
-rw-r–r–. 1 xyz xyz 0 Jul 2 19:01lmy.pcm
成功了 但是如果有文件名中有space 将会报错
doesn't work
原因:shell 以string 的形式读取mv {} $(basename {} .mp3).pcm
的时候{}最先被替换了命令变为了mv lmy.mp3 $(basename lmy.mp3 .mp3).pcm
这个时候再执行就正确了. 但是文件名有space肯定是错误的ls *.mp3|xargs -n1 -I{} sh -c 'mv {} ${{}/mp3/pcm}'
现在换个思路, 用string的替换,但是上面的命令也是错误的
doesn't work
原因:${var/substring/repstr} 这是bash的string替换的格式.很显然{}只是一个string不是一个变量ls *.mp3|xargs -n1 -I{} sh -c 'oldname={};mv $oldname ${oldname/mp3/pc}'
成功,文件有space 错误
doesn't work
ls *.mp3|xargs -n1 -I{} sh -c 'oldname="{}";mv "$oldname" "${oldname/mp3/pcm}"'
终于work了
find -name "*.mp3" -print0|xargs -0 -I{} sh -c'oldname="{}";mv "$oldname" "${oldname/mp3/pcm}"'
betterls *.mp3|awk '{split($1,a,".");print "mv " $1 " " a[1] ".pcm"}'|sh
再次换个思路 用awk 生成命令再用sh 执行
work 但文件名不能有space
ls *.mp3|awk -vFS="\n" '{split($1,a,".");print "mv " "\""$1"\"" " " "\""a[1] ".pcm""\""}'|sh
感觉太丑了不过还能用
work