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 ofbashparameter 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, runman bashand search forPattern 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
bashsolution,s/.../.../performs text substitution, but - unlike inbash- 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.
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 ofbashparameter 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, runman bashand search forPattern 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
bashsolution,s/.../.../performs text substitution, but - unlike inbash- 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.
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
First, do a dry run (will not actually rename any files) with the following:
for file in *.mov
do
echo mv "$file" "${file/MP4./}"
done
If it all looks fine, remove the echo from the third line to actually rename the files.
I just successfully used Automator (first time I've bothered), and it works really well. I saved the automation as a Service. It took about 10 seconds to make something easily reusable:
- Open Automator.
- As type of document, choose "Service".
- Change Service receives selected "Text" to "files and folders".
- Consider changing "any application" to just Finder.
- From the sidebar, select "Files & Folders" (under Library) and from the listed actions, in the center column, drag "Rename Finder items" to the right side and drop it within "Drag actions or files here to build your workflow."
- Change the action you just added from "Add Date or Time" to "Make Sequential".
- Click "Options" at the bottom of the action and check the option "Show this action when the workflow runs".
- Hit "CMD+S" to save the service as something like "Replace Text"..
- Done!
Now you can right-click any selection in Finder, go to the Service menu and select "Replace Text", fill in how you want the text changed or replaced - and click "Continue" to apply configured changes.
Automator - File rename script - Apple Community
Unix "rename" Terminal command available … - Apple Community
mac - How to rename multiple files at once? - Ask Different
regular expression - Rename file in Mac OS Terminal using Regex or translate from Windows Script - Unix & Linux Stack Exchange
Videos
Try something like this:
for file in Picture*.jpg
do
mv "$file" "vacation-$file"
done
(open terminal and add one line {press Enter} at a time.)
What that does is uses the variable file for each entry matching Picture*.jpg. Then it takes the file or folder and moves it to be prefixed with "vacation".
Hope that helps
No need for command line...
- Add all the images to be renamed into a folder.
- Select all files, right click mouse and select "Rename x items"
- Select "Add text" from first drop down menu
- Select "Before name" from the second drop down menu
- Enter "Vacation_" into the text box (without the quotation marks)
- Press Enter.
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.
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.
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'
I'm shocked I can't figure this out on my own.
I need to rename some photos located in a finder folder. I want to be able to select multiple photos and ask the user for a name and then simply increment the number i.e. photo 01, photo 02 etc etc.
How?
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:

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.
While you could precede each space with a \ character, you would be better of enclosing the entire file name with a pair of double quotes"", as shown below. Here I assume path is a variable, which also may contain spaces.
mv "$path/this is my app.ipa" "$path/this_is_my_app.ipa"
Or, a suppose you could also use the following.
mv "$path"/this\ is\ my\ app.ipa "$path"/this_is_my_app.ipa
If path is executable with output, then you are correct to use $(path).
Other answers explain the various ways to enquote or escape spaces. But as another option, tab-completion is your friend here and whenever you have filenames that are difficult to type — whether due to characters that need escaping, accented or otherwise unusual characters, or just length.
Specifically, if you start typing the command and current filename:
mv $(path)/thi
and then press tab, your shell should automatically complete to the escaped filename:
mv $(path)/this\ is\ my\ app.ipa
after which you can continue typing the command. (If you have multiple files whose names begin the same way, tab-completion should complete the name as far as the first ambiguous character.)
Separating the path_name from the file_name, something like.
#!/usr/bin/env bash
while read -r file; do
path_name="${file%/*}"; printf 'Path is %s\n' "$path_name"
file_name="${file#"$path_name"}"; printf 'Filename is %s\n' "$file_name"
newpath="$path_name${file_name//foo/bar}"
echo mv -v "$file" "$newpath"
done < <(find . -name "*foo*" -type f)
Have a look at basename and dirname as well.
The printf's is just there to show which is the path and the filename.
The script just replace foo to bar from the file_name, It can be done with the path_name as well, just use the same syntax.
newpath="${path_name//bar/more}${file_name//foo/bar}"
So renaming both path_name and file_name.
Or renaming the path_name and then the file_name like your idea is an option also.
path_name="${file%/*}"
file_name="${file#"$path_name"}"
new_pathname="${path_name//bar/more}"
mv -v "$path_name" "$new_pathname"
new_filename="${file_name//foo/bar}"
mv -v "${new_pathname%/*}$file_name" "$new_pathname$new_filename"
There are no additional external tool/utility used, except from the ones being used by your script.
Remove the echo If you're satisfied with the result/output.
You can use -execdir to run a command on just the filename (basename) in the relevant directory:
find . -depth -name '*foo*' -execdir bash -c 'mv -- "${1}" "${1//foo/bar}"' _ {} \;
With unix-like systems, it's easier to use find
find ./
(try this first to make sure that your list of files looks like what you were expecting
find ./ -exec mv ${} ${}.jpg \;
This will append .jpg to the end of every file found. The regex for changing the final extension, rather than just appending, is left as an exercise for the reader.
While using find and for loops are efficient, Perl usually comes with /usr/bin/rename (in Linux at least) but I'm not sure you have it on MacOSX (at least not in my old 10.3).
If you don't have it, you can get this script from the CPAN. And this is how to use it:
$ ls
tata.jpg titi.jpg toto.jpg truc tutu
$ rename -v 's/\.jpg$/.JPG/' *.jpg
tata.jpg renamed as tata.JPG
titi.jpg renamed as titi.JPG
toto.jpg renamed as toto.JPG
$ ls
tata.JPG titi.JPG toto.JPG truc tutu