开发者

Use bash-type `${i%.mp3}` syntax with xargs?

Example of usage (contrived!开发者_运维百科): rename .mp3 files to .txt.

I'd like to be able to do something like

find -name '*.mp3' -print0 | xargs -0 -I'file' mv file ${file%.mp3}.txt

This doesn't work, so I've resorted to piping find's output through sed -e 's/.mp3//g', which does the trick.

Seems a bit hackish though; is there a way to use the usual bash ${x%y} syntax?


No, xargs -0 -I'file' mv file ${file%.mp3}.txt will not work because the file variable will be expanded by the xargs program and not the shell. Actually it is not quite correct to refer to it as a variable, it is called "replace-str" in the manual of xargs.

Update: To just use xargs and bash (and no sed or similar) you can of course let xargs start a bash process which then can do whatever substitution you want:

find -name '*.mp3' -print0 | xargs -0 bash -c \
'while [ -n "$1" ]; do mv "$1" "${1%.mp3}.txt" ; shift; done;' "bash"


If you have GNU Parallel installed:

find -name '*.mp3' -print0 | parallel -0 mv {} {.}.txt

If your file names do not contain \n (newline) this will work too:

find -name '*.mp3' | parallel mv {} {.}.txt

Watch the intro video to learn more about GNU Parallel http://www.youtube.com/watch?v=OpaiGYxkSuQ


Just to add another suggestion, even though it doesn't use the shell's substitution mechanism, but instead, sed's.

find -name '*.mp3' -print |
sed -e 's/\.mp3$//' -e "s/.*/mv '&\.mp3' '&\.txt'/" |
sh

In other words, create an mv command line for each file name, and pass the result to sh.

This will fail if any of the files have an apostrophe (single quote) in their file name. I mainly post this to counter the "if all you have is xargs, every problem will look like a nail" syndrome.

Not all seds have exactly the same syntax. In particular, I'm not 100% sure you can have multiple -e arguments on some crufty old SunOS (look for the XPG-compatible sed in something like /usr/ucb/blah/barf/vomit/xpg4/bin/sed)


find . -type f -name '*.mp3' | while read -r F
do
  mv "$F" "${F%.mp3}.txt"
done

Bash 4+

shopt -s globstar
shopt -s nullglob
for file in **/*.mp3
do
    mv "$file" "${file%.mp3}.txt"
done


perl rename.pl 's/\.mp3$/.txt/' *.mp3  
# Or **/*.mp3 for zsh and bash with specific settings set, for a recursive 
# rename.

http://people.sc.fsu.edu/~jburkardt/pl_src/rename/rename.html

0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜