Batch renaming files in command line and Xargs

This can be also be done with xargs and sed to change the file extension.

ls | grep \.png$ | sed 'p;s/\.png/\.jpg/' | xargs -n2 mv

You can print the original filename along with what you want the filename to be. Then have xargs use those two arguments in the move command. For the one-liner, I also added a grep to filter out anything not a *.png file.


how do i rename the file so that I can just have one extension.

cd dir/with/messedup/files

for file in *.png.jpg; do
  mv "$file" "${file%.png.jpg}.jpg"
done

in the future, using xargs, how do I change the extension of the file simular to second command?

To my knowledge, that can't be done. The best way to do it would be to use a for-loop with parameter substitution much like the one above:

for file in *.png; do
  convert "$file" -resize "${file%.png}.jpg"
done

If you have files in subdirectories that you want converted, then you can pipe find to a while read loop:

find . -type f -name '*.png' |
while read file; do
  convert "$file" -resize "${file%.png}.jpg"
done

NOTE: It's generally considered a bad idea to use the output of ls in a shell script. While your example might have worked fine, there are lot's of examples where it doesn't. For instance, if your filenames happened to have newlines in them (which unix allows), ls probably won't escape those for you. (That actually depends on your implementation, which is another reason not to use ls in scripts; it's behavior varies greatly from one box to the next.) You'll get more consistent results if you either use find in a while-read loop or file globbing (e.g. *.png) in a for loop.