In your specific case you can use the following bash command (bash is the default shell on macOS):

for f in *.png; do echo mv "{f/_*_/_}"; done

Note: If there's a chance that your filenames start with -, place -- before them[1]:
mv -- "{f/_*_/_}"

Note: echo is prepended to mv so as to perform a dry run. Remove it to perform actual renaming.

You can run it from the command line or use it in a script.

  • "${f/_*_/_}" is an application of bash parameter expansion: the (first) substring matching pattern _*_ is replaced with literal _, effectively cutting the middle token from the name.
  • Note that _*_ is a pattern (a wildcard expression, as also used for globbing), not a regular expression (to learn about patterns, run man bash and search for Pattern Matching).

If you find yourself batch-renaming files frequently, consider installing a specialized tool such as the Perl-based rename utility. On macOS you can install it using popular package manager Homebrew as follows:

brew install rename

Here's the equivalent of the command at the top using rename:

rename -n -e 's/_.*_/_/'  *.png

Again, this command performs a dry run; remove -n to perform actual renaming.

  • Similar to the bash solution, s/.../.../ performs text substitution, but - unlike in bash - true regular expressions are used.

[1] The purpose of special argument --, which is supported by most utilities, is to signal that subsequent arguments should be treated as operands (values), even if they look like options due to starting with -, as Jacob C. notes.

Answer from mklement0 on Stack Overflow
Top answer
1 of 9
281

In your specific case you can use the following bash command (bash is the default shell on macOS):

for f in *.png; do echo mv "{f/_*_/_}"; done

Note: If there's a chance that your filenames start with -, place -- before them[1]:
mv -- "{f/_*_/_}"

Note: echo is prepended to mv so as to perform a dry run. Remove it to perform actual renaming.

You can run it from the command line or use it in a script.

  • "${f/_*_/_}" is an application of bash parameter expansion: the (first) substring matching pattern _*_ is replaced with literal _, effectively cutting the middle token from the name.
  • Note that _*_ is a pattern (a wildcard expression, as also used for globbing), not a regular expression (to learn about patterns, run man bash and search for Pattern Matching).

If you find yourself batch-renaming files frequently, consider installing a specialized tool such as the Perl-based rename utility. On macOS you can install it using popular package manager Homebrew as follows:

brew install rename

Here's the equivalent of the command at the top using rename:

rename -n -e 's/_.*_/_/'  *.png

Again, this command performs a dry run; remove -n to perform actual renaming.

  • Similar to the bash solution, s/.../.../ performs text substitution, but - unlike in bash - true regular expressions are used.

[1] The purpose of special argument --, which is supported by most utilities, is to signal that subsequent arguments should be treated as operands (values), even if they look like options due to starting with -, as Jacob C. notes.

2 of 9
129

To rename files, you can use the rename utility:

brew install rename

For example, to change a search string in all filenames in current directory:

rename -nvs searchword replaceword *

Remove the 'n' parameter to apply the changes.

More info: man rename

Discussions

Automator - File rename script - Apple Community
You can replace my do shell script content with the Tony T1's script. Assumption: no header row in the CSV and the delimiter is a comma. ... To answer an earlier question, the order of the filenames in your CSV and in the selected directory does not matter. Is the source of the CSV data from a Windows machine... More on discussions.apple.com
🌐 discussions.apple.com
August 1, 2019
Unix "rename" Terminal command available … - Apple Community
I am working under the assumption ... or bash script. Cheers, -J. ... I was working on some file operations today and I remembered that I actually once wrote a rename utility in perl for working on Windows. I brushed it off and took out all of the Windows wackiness (the command line doesn't expand blobs, etc.) and have another working solution. I'm not savvy enough to tell if it's better than the shell script from ... More on discussions.apple.com
🌐 discussions.apple.com
March 14, 2009
mac - How to rename multiple files at once? - Ask Different
I want to rename multiple files at once. For example: Picture1.jpg Picture2.jpg Picture3.jpg Picture4.jpg into Vacation-Picture1.jpg Vacation-Picture2.jpg Vacation-Picture3.jpg Vacation-Picture4... More on apple.stackexchange.com
🌐 apple.stackexchange.com
September 19, 2012
regular expression - Rename file in Mac OS Terminal using Regex or translate from Windows Script - Unix & Linux Stack Exchange
I would like help with a shell script for macOS to rename files with a certain pattern. More on unix.stackexchange.com
🌐 unix.stackexchange.com
November 18, 2023
🌐
nixCraft
cyberciti.biz › nixcraft › howto › bash shell › how to rename a file in bash
How To Rename A File In Bash - nixCraft
March 15, 2024 - How do I rename a file in bash under UNIX / macOS (OS X) / Linux / *BSD family operating systems using the command-line option? You need to use the mv command or rename command to rename a file in bash shell.
🌐
Apple Community
discussions.apple.com › thread › 250524625
Automator - File rename script - Apple Community
August 1, 2019 - I have tried the Rename Finder Items action of Automator, but I can't find the correct way to remove everything starting with the underscore (I have tried placeholder like * $ %). Anyone has an idea for the easiest way to keep 6 character (ideally not using Terminal command as I am not technical) ? Thanks ! 4689 9 ... All I did was show you the workflow that gets the selected folder as $1 and the chosen .csv file as $2 into the Run Shell Script.
🌐
Apple Community
discussions.apple.com › thread › 1760288
Unix "rename" Terminal command available … - Apple Community
March 14, 2009 - Now, the rename.c file does have a shell script at the top that is a very decent substitute: #!/bin/sh if [ $# -le 2 ]; then echo call: rename from to files; exit; fi FROM="$1" TO="$2" shift shift for i in $@; do N=`echo "$i" | sed "s/$FROM/$TO/g"`; mv "$i" "$N"; done but the compiled C program ...
Top answer
1 of 1
1

In zsh, from within the directory that contains those files, you'd run:

autoload -Uz zmv
zmv -n '*_ \((<0-999>)\)(* )—( * )(<1-12>)_(<1-31>)_(<1900-2100>)(.mp3)' \
       '2-6-{(l[2][0])4}-0900$7'

Example:

$ autoload -Uz zmv
$ zmv -n '*_ \((<0-999>)\)(* )—( * )(<1-12>)_(<1-31>)_(<1900-2100>)(.mp3)' \
         '2-6-{(l[2][0])4}-0900$7'
mv -- 'Public Talks_ (189) Walking With God Brings Blessings Now and Forever — Chris Ruscher 10_28_2023.mp3' '189 - Walking With God Brings Blessings Now and Forever - Chris Ruscher - 2023-28-10-0900.mp3'
mv -- 'Public Talks_ (55) How Can You Make a Good Name With God? — Gregory Duhon 11_4_2023.mp3' '055 - How Can You Make a Good Name With God? - Gregory Duhon - 2023-4-11-0900.mp3'
mv -- 'Public Talks_ (9) Walking With God Brings Blessings Now and Forever — Chris Ruscher 10_28_2023.mp3' '009 - Walking With God Brings Blessings Now and Forever - Chris Ruscher - 2023-28-10-0900.mp3'

Remove the -n (dry-run) if happy.

If that has to be a shell script that takes the file names as arguments:

#! /bin/zsh -
set -o extendedglob
pattern='(#b)*_ \((<0-999>)\)(* )—( * )(<1-12>)_(<1-31>)_(<1900-2100>)(.mp3)'
ret=0
for file {
  if [[ $file = $~pattern ]] {
    argv=( "$match[@]" )
    mv -i -- $file "2-6-{(l[2][0])4}-0900$7" || ret=$?
  } else {
    print -ru2 "Skipping $file which doesn't match the pattern"
  }
}
exit $ret

But you'd be missing on the extra safeguards of zmv.

Note that we're looping over all the arguments of the script instead of just processing the first ($1).

Find elsewhere
🌐
TheMacBeginner
themacbeginner.com › home › rename files and folders on mac using terminal
Rename files and folders on Mac using Terminal
October 6, 2022 - If you want your new file at the same location then type the same full path (or you can drag the file again and just edit the file name) with the new file name. The full command will look like this: mv /Users/chaitanyasingh/Documents/TheMacBeginner/MyFile2.txt /Users/chaitanyasingh/Documents/TheMacBeginner/MyNewFile.txt · If you want your renamed file at different location then instead of copying the same full path again just type the new file path with file name.
🌐
Stack Exchange
unix.stackexchange.com › questions › 652835 › renaming-all-files-in-a-certain-directory-and-sub-directory-on-macos
bash - Renaming all files in a certain directory and sub directory on MacOS? - Unix & Linux Stack Exchange
https://stackoverflow.com/questions/21985492/recursively-change-file-extensions-in-bash · And this works: find . -name "*.t1" -exec rename 's/\.t1$/.t2/' '{}' + Share · Improve this answer · Follow · answered Jun 4, 2021 at 18:20 · Ole · 74722 gold badges1212 silver badges2222 bronze badges 0 · Add a comment | Start asking to get answers · Find the answer to your question by asking. Ask question · Explore related questions · bash · shell-script · rename · macos ·
🌐
Apple Community
discussions.apple.com › thread › 1451230
Terminal command to rename files in bulk … - Apple Community
March 20, 2008 - You'll get a bunch of answers on how to do this, using foreach loops and various perl scripts. In zsh, which should be the OS X default shell, this is very easy. To start zsh, just type "zsh" To make it your default shell, just issue "chsh -s /bin/zsh" Once you are in zsh, you need do only two things (which you can put in your ~/.zshrc file for safe-keeping and automation):
🌐
ChrisWrites
chriswrites.com › how-to-batch-rename-files-in-mac-os-x
How to Batch Rename Files in Mac OS X - ChrisWrites.com
JavaScript is disabled in your browser · Please enable JavaScript to proceed · A required part of this site couldn’t load. This may be due to a browser extension, network issues, or browser settings. Please check your connection, disable any ad blockers, or try using a different browser
🌐
Reddit
reddit.com › r/commandline › please help me rename files in batch on macos terminal
r/commandline on Reddit: Please help me rename files in batch on macOS terminal
August 22, 2023 -

Hello All, TLDR at the end.

I am trying to rename files in batch on macOS terminal. I tried to read online for this, but I could not figure out a way to do this on my own. Below is an example of what I am trying to achieve,

file1.webp file45sa.webp randomname.webp I want to rename all the files to JPEG, but preserve their original name and just change the extension. Rename to: file1.jpeg file45sa.jpeg randomname.jpeg

Please let me know how this can be done? For context, I am using ImageMagick tool.

tl;dr: convert all .webp files to .jpeg files on Mac terminal using imagemagick. Asking this question here as it is related to commandline logic rather than imagemagick.

Top answer
1 of 3
4

You are encountering one of the reasons why it is recommended to (almost) always quote your shell variables.

In your case, since you assign to the shell variable fichier a file name that contains whitespace, the shell will perform word splitting when you use that variable "as is", i.e. just as $fichier. That means that a directory Job offers etc as argument to mv would be interpreted as trying to move the three files Job, offers and etc to the destination directory Job_offers_etc(1).

In order to avoid the problem, place double-quotes around the variable reference, as in "$fichier".


(1) This can actually be dangerous; in some settings, if the destination directory doesn't exist, the command may lead to three files being renamed to the same name, effectively overwriting the first two by the third one.

2 of 3
3

If you have the perl rename utility, File::Rename, already installed, this is easy. If you don't already have it, you should install it - it makes difficult bulk-renaming operations trivially easy.

If you have Homebrew installed, you can install it with brew install rename (see rename on brew), otherwise you can install it with cpan. Again, if you don't have Homebrew installed on your Mac, you should, it gives you access to thousands of packages.

Then you can replace spaces with underscores in all filenames + directory names in the current directory with just:

rename -n 's/ /_/g' *

The -n option makes this a dry-run, it won't actually rename any files, it will just show you what would be renamed. Once you're sure it does what you want, remove the -n option or replace it with -v for verbose output.

There's little or no need to exclude files that don't contain a space because perl rename will only attempt to rename a file if the filename was actually changed by your rename script, and the script above won't change filenames without a space.

It will also refuse to rename a file over an existing filename unless you force it to with -f.

You can use it with find if you want, and it understands NUL-separated input (so it works with any filenames, even those with linefeeds in them). e.g.

find . -maxdepth 1 -iname "* *" -print0 | rename -0 -n 's/ /_/g'
Top answer
1 of 2
11

For command line script to rename, this stackoverflow question has good answers.

For Mac, In GUI, Finder comes with bulk rename capabilities. If source list of files has some pattern to find & replace, it comes very handy.

Select all the files that need to be replaced, right click and select rename

On rename, enter find and replace string

Other options in rename, to sequence the file names:

To prefix or suffix text:

2 of 2
7

First, I should say that the easiest way to do this is to use the prename or rename commands.

Homebrew package rename, MacPorts package renameutils :

rename s/0000/000/ F0000*

That's a lot more understandable than the equivalent sed command.

But as for understanding the sed command, the sed manpage is helpful. If you run man sed and search for & (using the / command to search), you'll find it's a special character in s/foo/bar/ replacements.

  s/regexp/replacement/
         Attempt  to match regexp against the pattern space.  If success‐
         ful,  replace  that  portion  matched  with  replacement.    The
         replacement may contain the special character & to refer to that
         portion of the pattern space  which  matched,  and  the  special
         escapes  \1  through  \9  to refer to the corresponding matching
         sub-expressions in the regexp.

Therefore, \(.\) matches the first character, which can be referenced by \1. Then . matches the next character, which is always 0. Then \(.*\) matches the rest of the filename, which can be referenced by \2.

The replacement string puts it all together using & (the original filename) and \1\2 which is every part of the filename except the 2nd character, which was a 0.

This is a pretty cryptic way to do this, IMHO. If for some reason the rename command was not available and you wanted to use sed to do the rename (or perhaps you were doing something too complex for rename?), being more explicit in your regex would make it much more readable. Perhaps something like:

ls F00001-0708-*|sed 's/F0000\(.*\)/mv & F000\1/' | sh

Being able to see what's actually changing in the s/search/replacement/ makes it much more readable. Also it won't keep sucking characters out of your filename if you accidentally run it twice or something.

🌐
Apple Community
discussions.apple.com › thread › 1953614
mv command - quickest way to rename? - Apple Community
March 28, 2009 - #!/usr/bin/perl -w use strict; use File::Basename; my $path = shift; my $newname = shift; rename $path, dirname($path) .
🌐
MacScripter
macscripter.net › scripting forums › applescript | mac os x
Script to Rename Selected File - AppleScript | Mac OS X - MacScripter
January 28, 2022 - I have found this script and I would like to modify it to do what I expect it to do: tell application "Finder" set theFile to (choose file) set name of theFile to "artwork.png" end tell So here’s what I need: 1 - I would like to create a Service out of this script so I can just access it ...