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?

  • 1
    So... you want to rename README to README.mp4? Oct 2, 2016 at 15:41
  • @ThomasDickey Believe me when I say that all of the files that have no file extensions in those folders are MP4 video files. No README. But I understand your concern.
    – ThoWe
    Oct 2, 2016 at 15:52

4 Answers 4


Something like this:

find . -type f  ! -name "*.*" -exec mv {} {}.mp4 \;
  • 3
    can also do it as find . -type f ! -name "*.*" -exec bash -c 'mv "$0" "$0".mp4' {} \;
    – Sundeep
    Oct 2, 2016 at 15:50
  • 1
    The form from @Sundeep is better because it's actually specified in POSIX. Using multiple arguments containing {} may not work on all systems.
    – Wildcard
    Nov 8, 2016 at 8: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


$ find -type f

$ 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)
  • 1
    Thanks 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 2, 2016 at 15:47

globstar way:

# 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 ;;       
   mv "$f" "$f".mp4;

perl way, adding _2 if target exists in order to avoid overwrite

use warnings;
use strict;

use File::Find;

find(\&rout, ".");
sub rout {
    next if -d $_;
    my $new_name = $_;
    $new_name    =~ s/^([^.]+)$/$1.mp4/;     
    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 $!;

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

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.