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