DEV Community

Ndimah Tchougoua
Ndimah Tchougoua

Posted on

Brash one-liner to rename files Matching a pattern

One day I found myself in the situation where I needed to rename a series of files by removing a pattern on Each file. Guess what ? They were around 150 PDF files, so no way for me to do it manually.
While searching on the internet, I found the term brash one-liner. It's a kind of long series of bash command combined in order to achieve a goal.
So I had to define mine in order to solve my problem. After a lot of experimentations, I came out with this brash one-liner :

pattern='some-pattern'; find -type f -iname "*$pattern*" | xargs -0 -I{} echo "file=\"{}\"; mv \"\$file\" \"\${file//\"$pattern\"/} " | bash
Enter fullscreen mode Exit fullscreen mode

Looks cryptic? Yeah, you're right, it is a little bit.
So let me explain my approach to solve this problem.
My approach to solve it uses 4 steps:

  • Pattern Definition
  • Files Searching
  • Text-Based bash command definition
  • Command Execution

Pattern Definition

   pattern='some-pattern';
Enter fullscreen mode Exit fullscreen mode

here I just keep my pattern in a variable to avoid repeating myself (I'm a DRY guy)
Note: I use the single quotes here because my pattern don't need to be evaluated before execution by the shell

Files Searching

  find -type f -iname "*$pattern*"
Enter fullscreen mode Exit fullscreen mode

Here I search for all files matching my pattern, ignoring the case with the help of the find command
Note: we have to ensure ourselves that the pattern only matches the files we are looking to rename, otherwise it's going to rename the unexpected files. Please try to run this separately first to verify it.

Text-Based bash command definition

   xargs -0 -I{} echo "file=\"{}\"; mv \"\$file\" \"\${file//\"$pattern\"/} "
Enter fullscreen mode Exit fullscreen mode

This is where the magic operate, so we have to use a little trick to define the new name of each file.
Here, my approach is to use shell expansion.
I've chosen to use the xargs command because it will execute the same command for each file found.
The -0 argument here is to end each entry with the null character.
The -I{} is to tell xargs to replace all occurrences of {} in the command with the entry.
Inside my text-based command, I define a so that I will substitute all occurrences of $pattern with a blank character.
I've used the escape character to avoid the file variable to be evaluated before execution.
Note: I could've used the sed command, but I wanted to reduce typing. By the way, this is the place where we can build any complex command, so it's up to your imagination.

Command Execution

   bash
Enter fullscreen mode Exit fullscreen mode

Here is where the bash come to the game and execute the text-based bash command that it receives.

At the end of the day, I hope that this little tutorial will help you if you face this type of problem. Feel free to send me any suggestion or improvement in the discussion, thank you for your attention.

Top comments (0)