Rename all files and directory names

Posted under » Linux on 09 November 2017

You might have to apt install rename if the following does not work.

$ rename 's/txt/TXT/g' atxt.txt  
$ rename 's/txt/TXT/g' *
$ rename 's/.text/.txt/i' *  //case insensitive

It is very like VIM replace.

You can do something similar to PERL regex.

$ rename 's/(\w+)-(\w+)-(\d\d)-(\d{4})-NODATA.txt/$1.$4$3$2.log$//' *
$ rename 's/^x/$1/' *.mp4 // will remove the initial x

To lowercase or upper

The most basic way

$ rename 'y/A-Z/a-z/' *.JPG

However, the extension will also be changed to lowercase. When you want just the name.

$ rename  -n 's/.*\./\U$&/'
-n argument is for not making changes and show you what's going to happen.
.* argument in regex world is select everything, used together with \. is to select everything before the dot[.]
.*\. select everything before the dot.
Escape characters with \[backslash] because .[dot] has special meaning in regex.
\U argument means uppercase until, this is an Escape sequence in Perl regular expressions, it has to be used with \[backslash]
\L is lowercase as in example below
$& argument is used to find the string matched in the last successful pattern search. example /find/$&ADD/ returns: findADD

Using Find and depth

For the purpose of this guide, we have used a directory named Images which has the following structure:

find Images -depth

-depth lists each directory's contents before the directory itself. So lets rename them.

find Images -depth | xargs -n 1 rename -v 's/(.*)\/([^\/]*)/$1\/\L$2/' {} \;
Where $1 is the depth (Images) while $2 is the filename

Using mv and bash

Another alternative way using the find and mv commands in a bash script as explained below. Lets call this script "rename-files.sh".

#!/bin/bash
#print usage 
if [ -z $1 ];then
echo "Usage :$(basename $0) parent-directory"
exit 1
fi
#process all subdirectories and files in parent directory
all="$(find $1 -depth)"
for name in ${all}; do
#set new name in lower case for files and directories
new_name="$(dirname "${name}")/$(basename "${name}" | tr '[A-Z]' '[a-z]')"
#check if new name already exists
if [ "${name}" != "${new_name}" ]; then
[ ! -e "${new_name}" ] && mv -T "${name}" "${new_name}"; echo "${name} was renamed to ${new_name}" || echo "${name} wasn't renamed!"
fi
done
echo
echo
#list directories and file new names in lowercase
echo "Directories and files with new names in lowercase letters"
find $(echo $1 | tr 'A-Z' 'a-z') -depth
exit 0

Then run it like so

rename-files.sh Images

If you want to change your files extension, unfortunately "mv *.xml *.txt" will not work. You have to use some bash and regex for this.

# Rename all *.xml to *.txt
for f in *.xml; do 
    mv -- "$f" "${f%.xml}.txt"
done

web security linux ubuntu python django git Raspberry apache mysql php drupal cake javascript css AWS data