Skip to main content
Linux Scripting:

How to rename files based on pattern in Linux

Summary

How to rename files in bulk - based on a pattern / string - using a shell command that leverages Bash's parameter expansion. Practical examples and command break downs. Highlights the advantages over external tools like rename or sed.

Introduction #

Renaming files in bulk is a common and tedious task when managing files. In this article I will demonstrate how to rename files by replacing specific parts of their filenames using a simple shell command.

I will work with example files and explain how the used commands works, making it easy to adapt them for similar tasks.

The examples in this article refer to the following three example files:

$ tree 
.
├── foo-example-1.txt
├── foo-example-2.txt
└── foo-example-3.txt

Single change on multiple files #

The goal is to rename the foo part in each file name to bar. So that the list looks like this:

$ tree 
.
├── bar-example-1.txt
├── bar-example-2.txt
└── bar-example-3.txt

The following shell command renames all .txt files in the current directory by replacing occurrences of the string foo with bar in their filenames.

for file in ./*.txt ; do mv "$file" "${file//foo/bar}" ; done

Breakdown:

  • for file in ./*.txt ; do ... ; done
    • This for loop iterates over all .txt files in the current directory (./).
    • The file variable holds the filename of each file during each iteration.
  • mv "$file" "${file//foo/bar}"
    • mv is the command to rename (move) files.
    • "$file" is the current file’s name (quoted to handle spaces or special characters).
    • "${file//foo/bar}" is a parameter expansion that replaces all occurrences of foo with bar in the filename.

The replacement is case-sensitive.

This option is ideal. It makes use of Bash’s Shell Parameter Expansion and does not require the rename or sed packages. Both packages are often not preinstalled (Ubuntu), or even only available in user repositories, e.g. rename in Arch Linux.

Multiple changes on multiple files #

Let us adjust the above command by applying two replacements sequentially within the loop, so that not only foo is renamed to bar but also example will be renamed to sample. Here’s the modified command:

for file in ./*.txt; do
  new_file="${file//foo/bar}"  # Replace 'foo' with 'bar'
  new_file="${new_file//example/sample}"  # Replace 'example' with 'sample'
  mv "$file" "$new_file"  # rename file
done

Breakdown:

  • ${file//foo/bar}: Replaces foo with bar.
  • ${new_file//example/sample}: Applies the second replacement, changing example to sample.
  • mv "$file" "$new_file": Renames the file using the updated name.

The replacement is case-sensitive.

After using the command, the files will look like this:

$ tree 
.
├── bar-sample-1.txt
├── bar-sample-2.txt
└── bar-sample-3.txt

Case-insensitive command #

To make the command case-insensitive, you can use bash’s built-in features like shopt -s nocaseglob, which makes filename expansion case-insensitive.

for file in ./*.txt; do 
  # Convert filename to lowercase using `tr`
  lower_file=$(echo "$file" | tr '[:upper:]' '[:lower:]')
  
  # Perform replacements
  new_file="${lower_file//foo/bar}"
  new_file="${new_file//example/sample}"
  
  # Rename the file
  mv "$file" "$new_file"
done

shopt -u nocaseglob  # Disable case-insensitive file matching

Breakdown:

  • shopt -s nocaseglob: Enables case-insensitive matching for files.
  • tr '[:upper:]' '[:lower:]': Converts the entire filename to lowercase.
  • ${new_file//foo/bar} and ${new_file//example/sample}: Perform string replacements.
  • mv "$file" "$new_file": Renames the file.

Further readings #

Sources and recommended, further resources on the topic:

Author

Jonas Jared Jacek • J15k

Jonas Jared Jacek (J15k)

Jonas works as project manager, web designer, and web developer since 2001. On top of that, he is a Linux system administrator with a broad interest in things related to programming, architecture, and design. See: https://www.j15k.com/

License

How to rename files based on pattern in Linux by Jonas Jared Jacek is licensed under CC BY-SA 4.0.

This license requires that reusers give credit to the creator. It allows reusers to distribute, remix, adapt, and build upon the material in any medium or format, for noncommercial purposes only. To give credit, provide a link back to the original source, the author, and the license e.g. like this:

<p xmlns:cc="http://creativecommons.org/ns#" xmlns:dct="http://purl.org/dc/terms/"><a property="dct:title" rel="cc:attributionURL" href="https://www.ditig.com/how-to-pattern-based-rename-multiple-files">How to rename files based on pattern in Linux</a> by <a rel="cc:attributionURL dct:creator" property="cc:attributionName" href="https://www.j15k.com/">Jonas Jared Jacek</a> is licensed under <a href="https://creativecommons.org/licenses/by-sa/4.0/" target="_blank" rel="license noopener noreferrer">CC BY-SA 4.0</a>.</p>

For more information see the Ditig legal page.

All Topics

Random Quote

“Make errors impossible. Making it impossible for the user to make errors is the best way to eliminate error messages.”

Alan Cooper  Software designer and programmerAbout Face, - IT quotes