Append text to file names which do not contain a dot

Given the following files:

english_api
english_overview
style.css

I want to get:

english_api.html
english_overview.html
style.css

In other words how to append a text to all files that do Not Contain a dot (.) within a directory using terminal.

Obviously there is a lot of files in that folder; I just wrote 3 as an example.

If I were to, lets say, replace .css with .html in that folder, I would use:

rename .css .html *.css

But I cannot really think of a way to match files that do not contain something. Also how to append (vs replace) using rename command?


Solution 1:

Try this find command,

find . -type f ! -name "*.*" -exec mv {} {}.html \;

It renames the files which doesn't contain dots in their filenames present in the current directory to this filename.htmlformat(added .html at the last).

. --> Represents current directory

-type f --> To do this operation only on files.

! -name "*.*" --> print the name of the files which doesn't have dots in their name.

-exec mv {} {}.html --> find command perform this move(or)rename operation on the extracted filenames.

\; --> Represents the end of find command.

Solution 2:

In bash, you could use extended shell globs e.g.

for file in path/to/files/!(*.*); do echo mv "$file" "$file.html"; done

(remove the echo once you've confirmed it is matching the correct pattern). If extended globbing is not already enabled, you can enable it with shopt -s extglob.

Another option is using the perl-based rename function with a regex that excludes literal .

rename -nv 's/^[^.]+$/$&.html/' path/to/files/*

(remove the n option once you have confirmed it is matching the correct pattern).

Solution 3:

My prefered in cases like this is mmv. It is not installed by default in Ubuntu, but you can install using sudo apt-get install mmv command.

In your case you need to use it two times:

  1. Rename all files from current directory by adding .html at the end of each file name:

    mmv -v '*' '#1.html'
    
  2. Rename again (back) all files which had previously in their names one or more . (dots):

    mmv -v '*.*.html' '#1.#2'
    

Or, in one line:

mmv -v '*' '#1.html' && mmv -v '*.*.html' '#1.#2'

-v option is not mandatory. I use it only for a verbose output because without it mmv performs actions silently.

See man mmv for more info.