tags:

views:

42

answers:

3

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?

A: 
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
ghostdog74
I know how to do this; the purpose of the question is to see if it's possible to do this with xargs, and have it not immediately expand replace-str (I guess).
A: 

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"
hlovdal
Any way to have the shell expand the expression, before xargs does its thing?
A: 

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

Ole Tange