xargs 常见于批处理, 下面举个例子:将一个目录中的mp3文件改为pcm后缀名,下面的方法从错误一步步的改进并分析

  1. 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:45 lmy.mp3.pcm

    does't work.
    原因: shell 最先执行子命令$(basename {} .mp3), 所以{}不会被替换. 它在一个新的进程中将执行的结果返回就是{}, 所以最初的命令变为mv {} {}.pcm 这时候进行{}的替换, 所以结果是 lmy.mp3.pcm

  2. 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:01 lmy.pcm

    成功了 但是如果有文件名中有space 将会报错doesn't work
    原因:shell 以string 的形式读取mv {} $(basename {} .mp3).pcm 的时候{}最先被替换了命令变为了mv lmy.mp3 $(basename lmy.mp3 .mp3).pcm 这个时候再执行就正确了. 但是文件名有space肯定是错误的

  3. ls *.mp3|xargs -n1 -I{} sh -c 'mv {} ${{}/mp3/pcm}'

    现在换个思路, 用string的替换,但是上面的命令也是错误的doesn't work
    原因:${var/substring/repstr} 这是bash的string替换的格式.很显然{}只是一个string不是一个变量

  4. ls *.mp3|xargs -n1 -I{} sh -c 'oldname={};mv $oldname ${oldname/mp3/pc}'

    成功,文件有space 错误doesn't work

  5. ls *.mp3|xargs -n1 -I{} sh -c 'oldname="{}";mv "$oldname" "${oldname/mp3/pcm}"'

    终于work了

  6. find -name "*.mp3" -print0|xargs -0 -I{} sh -c'oldname="{}";mv "$oldname" "${oldname/mp3/pcm}"'
    better

  7. ls *.mp3|awk '{split($1,a,".");print "mv " $1 " " a[1] ".pcm"}'|sh

    再次换个思路 用awk 生成命令再用sh 执行

    work 但文件名不能有space

  8. ls *.mp3|awk -vFS="\n" '{split($1,a,".");print "mv " "\""$1"\"" " " "\""a[1] ".pcm""\""}'|sh

    感觉太丑了不过还能用work


dreambei
132 声望4 粉丝

引用和评论

0 条评论