Habib Inman
Habib Inman

Reputation: 181

Renaming Files Through Script

I have a few files that are incorrectly named (with the extension added twice to the end). I was trying to write a bash script that would scan the directory and rename them, but it throws an error of:

cannot move ‘/var/random/file/file1.avi.mp4’ to ‘{/var/random/file/file1.avi.mp4%.avi.mp4}.mp4’: No such file or directory

I just want to properly rename the file extension, and am not sure where the error comes into play. For example, the error above, should have a file extension of .mp4. Below is my script, if someone could assist, I would be in debted...

#/bin/sh
for file in $(find /var/random/ -type f -name "*.avi.mp4"); do
  mv "$file" "{$file%.avi.mp4}.mp4"
done

Upvotes: 2

Views: 78

Answers (2)

sjsam
sjsam

Reputation: 21965

find . -type f -name "*.avi.mp4" -print0 | while read -rd '' filename
do
if [ -e "${filename%.avi.mp4}.mp4" ]
then
  mv --backup "${filename}" "${filename%.avi.mp4}.mp4"
  #doing the backup only if the destination file exists to save space.
else
  mv "${filename}" "${filename%.avi.mp4}.mp4"
fi
done

What happened here :

  1. We find out all the files ending with .avi.mp4 extension.
  2. Since the file can contain newline characters, we make the filenames null terminated using print0 option of the find.
  3. This output is piped into while loop where we are ready to parse the files.
  4. Setting the delimiter -d option of the read to null('') command we parse each of the null terminated filenames.
  5. Finally we use parameter expansion/substitution to get rid of the .avi.mp4 at end of each file and append a .mp4 to each file at the mv phase. See reference 1.

References :

  1. Shell parameter expansion
  2. Move manual
  3. Why use while instead of for?

Upvotes: 2

Andreas Louv
Andreas Louv

Reputation: 47127

You have a typo in your variable expansion:

"{$file%.avi.mp4}.mp4"

should have been:

"${file%.avi.mp4}.mp4"

However you might want to take a look at rename (perl-rename)

perl-rename 's/[^.]+\.(?=[^.]+$)//' /var/random/*/*.avi.mp4

The regex will remove the second to last extension in file names:

/path/to/file/foo.bar.baz -> /path/to/file/foo.baz

Upvotes: 4

Related Questions