Assuming I want to change some filenames that end with jpg.jpg to end only with .jpg (in bash), and I want to do it by piping the output of find to xargs:
By using sed:
find . -iname '*jpg.jpg' | xargs -I % mv -iv % $(echo % | sed 's/jpg.jpg/.jpg/g')
However, this does not replace jpg.jpg with .jpg in the destination file of mv.
By using awk:
find . -iname '*jpg.jpg' | xargs -I % mv -iv % $(echo % | awk '{gsub(/jpg.jpg/,".jpg")}; 1')
This neither does any replacement. Have I missed something?
I would do this by writing a script that takes filenames and does the rename:
#!/bin/sh
for FILE
do
mv $FILE `basename $FILE jpg.jpg`.jpg
done
That script is easily called via xargs.
If you want to smash it onto a single command line you can do it but it's usually not worth the trouble.
EDIT: If I had to do it on one command line I'd probably use a different trick without xargs: Use sed to turn the output of find into a shell script:
find . -iname '*jpg.jpg' | sed -e 's/\(.*\)jpg\.jpg$/mv & \1.jpg/' | sh
The advantage of xargs being able to fork off fewer children is defeated by the need to run mv repeatedly anyway. If you really need that advantage you need a solution like my first option but coded in something like perl which can execute multiple rename() calls without forking off any mv.
If you have the rename command available on your system, then the following command should work:
rename 's/(.*)jpg.jpg/$1.jpg/g' *jpg.jpg
The $(...) is evaluated by bash before running xargs, so xargs just sees the output of that expression as it currently stands as the second argument to mv.
So it is equivalent to:
... | xargs -I % mv % %
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With