I have hundreds of files in various different subdirectories. Some of them have the correct file extension, but some of them don't. I want to rename all files that don't have a file extension and append a .mp4 extension to their file name. The other files should be left untouched. How can I automate this renaming operation using Bash? Or do I need a real scripting language like Perl or Python for this?
4 Answers
Something like this:
find . -type f ! -name "*.*" -exec mv {} {}.mp4 \;

- 829,060

- 354
-
3can also do it as
find . -type f ! -name "*.*" -exec bash -c 'mv "$0" "$0".mp4' {} \;
– Sundeep Oct 02 '16 at 15:50 -
1The form from @Sundeep is better because it's actually specified in POSIX. Using multiple arguments containing
{}
may not work on all systems. – Wildcard Nov 08 '16 at 08:30
Try this:
find -type f -not -name '*.mp4' -exec rename -n 's/$/.mp4/' {} +
This checks for all files in current directory and its sub-folders that do not end with .mp4
and renames them to add the extension
Assumes perl
based rename
command, -n
option is to show how the files will be renamed. Once you are okay with it, remove the option and run the command again
Example:
$ find -type f
./rand_numbers.txt
./tst
./abc/123
./abc/zyx.txt
$ find -type f -not -name '*.mp4' -exec rename -n 's/$/.mp4/' {} +
rename(./rand_numbers.txt, ./rand_numbers.txt.mp4)
rename(./tst, ./tst.mp4)
rename(./abc/123, ./abc/123.mp4)
rename(./abc/zyx.txt, ./abc/zyx.txt.mp4)
If you define file not having extension to mean file names without .
in their name, use:
$ find -type f -not -name '*.*' -exec rename -n 's/$/.mp4/' {} +
rename(./tst, ./tst.mp4)
rename(./abc/123, ./abc/123.mp4)

- 12,008
-
1Thanks for your answer. I guess the
find -type f -not -name '*.*' -exec rename -n 's/$/.mp4/' {} +
command does the job (I cannot assume that all other files have .mp4 that's why your first solution doesn't work for me). As I don't have the perl based rename command installed I've used the variant with the mv command instead. – ThoWe Oct 02 '16 at 15:47
globstar way:
#!/bin/bash
# Warning: globstar excludes hidden directories.
# Turn on recursive globbing (in this script) or exit if the option is not supported:
shopt -s globstar || exit
for f in **; do
if [ -f "$f" ]; then
case "${f##*/}" in
*.*) continue ;;
esac
mv "$f" "$f".mp4;
fi
done
perl way, adding _2 if target exists in order to avoid overwrite
#!/usr/bin/perl
use warnings;
use strict;
use File::Find;
find(\&rout, ".");
sub rout {
next if -d $_;
my $new_name = $_;
$new_name =~ s/^([^.]+)$/$1.mp4/;
chdir($File::Find::dir);
if(-e $new_name){
my $new_name2 = $_;
$new_name2 =~ s/^([^.]+)$/$1\_2.mp4/;
rename($_, $new_name2) or die $!;
} else {
$new_name =~ s/^([^.]+)$/$1.mp4/;
rename($_, $new_name) or die $!;
}
}

- 303
This will rename all files in current directory that DO NOT already have a file extension..
Example: your directory has files named: file1, file2, file3. They will be renamed to file1.mp4, file2.mp4, file3.mp4
for file in *; do
mv "$file" "${file}.mp4"
done
If there are files with a dot which must be excluded:
for file in *; do
[[ $file == *.* ]] && continue
mv "$file" "${file}.mp4"
done
Or with shopt -s extglob:
for file in +([^.]); do
mv "$file" "${file}.mp4"
done

- 1
-
for file in *; do \ mv "$file" "${file}.mp4" \ done
appears to append to any existing file extensions. Fedora 38.
– user598527 Oct 19 '23 at 12:01
README
toREADME.mp4
? – Thomas Dickey Oct 02 '16 at 15:41