Rename a batch of files using a Terminal bash command

Maith Egeek
3 min readJan 31, 2022

Moving all files corresponding to a string

for i in *.yourfiles; do mv "$i" "`echo $i | sed 's/old/new/g'`"; done

And if you want to use it often like I do:

rename 's/old/new/' *.files

I recommend to use this little script in ~/bin/renamescript:

#!/usr/bin/env zsh
SUBSEXPR=$1
shift
for i in $@; do mv $i `echo "$i" | sed $SUBSEXPR`; done

Numbered filenames in a folder

If filenames have a number appended to them and if you have your numbers between 1 and 999 (included), here is a line that will automatically increment the number in each filename by 1 :

for i in {999..1}; do mv nameroot$i.extension path/to/new/folder/nameroot$((i+1)).extension; done

This example illustrate the case when in your folder you had files named:

chapter1.tex
chapter2.tex
chapter3.tex
chapter4.tex
chapter5.tex
chapter6.tex

With this script, you now obtain a folder with files named :

chapter2.tex
chapter3.tex
chapter4.tex
chapter5.tex
chapter6.tex
chapter7.tex

It will also output errors for the non-existing filenames, such as :

mv: cannot stat ‘*101.tex’: No such file or directory

The order 999 to 1 in the loop in this example has the advantage to avoid processing the newly renamed file if we remain in the same folder, but most of all, this allows the processing of all files only once, as filenames would then be selected by the number and not only by the digits (for instance the case of nameroot1.extension nameroot11.extension and nameroot21.extension)

And here is the better formatted version:

for i in {999..1}; do
mv nameroot$i.extension path/to/new/folder/nameroot$((i+1)).extension;
done

For each i from 999 to 1, the loop renames nameroot<value of i>.extension to nameroot<value of i+1>.extension.

A dataset in several folders

Now, imagine you have a dataset with files numbered in each folder, and the data from files with the same numbering correspond to the same recording, but there might be missing data in some folders. For instance you have in :

  • folder rgbrecordings: video1.avi, video2.avi, video3.avi, video5.avi
  • folder audiorecordings: audio_subjectA_1.mp3, audio_subjectB_2.mp3, audio_subjectA_4.mp3. audio_subjectB_5.mp3

audio-subjectA_1.mp3 are thus audio files corresponding to video1.avi. There are also missing files such as video4.avi or audio3.mp3. The names in audiorecordings folder encode more information.

What you wish is to get folder of rgb recordings that has a matching audio recording, so as to constitute a complete database. In our example our new folder would have the files :

video1.avi, video2.avi, video5.avi

To move all files from a folderA corresponding to any file from folderB to folderC, with the filename given by the file from folderB — in other words, to copy all files from folderA to folderC by keeping the numbering but changing the filename — you can adapt this script, written for numberings from 100 to 1:

cd path/to/folderBfor i in {100..1};do FILENAMEI=$(ls *$i*.extension1); mv path/to/folderA/nameroot$i.extension2 path/to/folderC/$FILENAMEI; done;

Like previously, the script can output error messages, due to non existing files :

mv: cannot stat ‘path/to/folderA/nameroot998.extension2’: No such file or directory
ls: cannot access ‘*007*.extension1’: No such file or directory

The above script has 2 big defaults :

  • the filenames in the new folder have the extension extension1, which does not correspond to their true extension, which is extension2.
  • if there are missing files in folderB, this command would delete from folderA the file path/to/folderA/nameroot$i.extension2.

In our previous example, folder rgbrecordings is empty after executing the script, while we were expecting file video3.avi to still be in the folder.

To keep the files in folderA that do not correspond to any file in folder B, and to keep the original file’s extension :

cd path/to/folderBfor i in {100..0};do FILENAMEE=""; FILENAMEE=$(ls *$i.extension1);FILENAMEI="";FILENAMEI="${FILENAMEE%%.*}"; if [ ! -z "$FILENAMEI" ]; then  mv path/to/folderA/nameroot$i.extension2 path/to/folderC/$FILENAMEI.extension2; fi; done

As previously, the script can still give — which is normal — errors such as :

ls: cannot access ‘*099.extension1’: No such file or directory

With this bash script:

  • our rgbrecordings folder ends up with the file: video3.avi.
  • the new folder contains files : video1.avi, video2.avi, video5.avi

Extract the various parts of a filename

Indeed, the command

FILENAMEI="${FILENAMEE%%.*}"

extracts the filename’s root before the extension.

To extract the various parts of a path and filename

FILE="example.extension1.extension2"

~% echo "${FILE%%.*}"
example

~% echo "${FILE%.*}"
example.extension1

~% echo "${FILE#*.}"
extension1.extension2

~% echo "${FILE##*.}"
extension2

--

--