How to Rename Files in Terminal on Mac

Mac Terminal provides several powerful methods for renaming files: the built in mv command, shell for loops for batch operations, and the rename Perl utility installed through Homebrew. This guide covers every Terminal approach from single file renames to complex regex transformations.

How Do You Rename a Single File in Terminal on Mac?

The mv command renames a single file in Terminal on Mac. The syntax is mv oldname.txt newname.txt where the first argument is the current filename and the second argument is the desired filename. The file stays in the same directory when both arguments share the same path.

The mvcommand is built into macOS and requires no installation. Open Terminal from Applications, Utilities, or by pressing Cmd+Space and typing "Terminal." Navigate to the directory containing your file with cd /path/to/directory and run mv report_draft.txt report_final.txt to rename the file instantly.

Quoting filenames is essential when they contain spaces or special characters. The command mv "My Document.txt" "My Report.txt" handles spaces correctly because the quotes prevent the shell from splitting the filename into separate arguments. Unquoted filenames with spaces cause the shell to interpret each word as a separate file, which produces errors or renames the wrong files entirely.

The mv command overwrites existing files without warning by default. Running mv notes.txt readme.txt when readme.txt already exists destroys the original readme.txt silently. The -i flag adds an interactive prompt: mv -i notes.txt readme.txt asks for confirmation before overwriting. The -n flag prevents overwriting entirely by refusing to replace any existing file.

How Do You Batch Rename Files Using a for Loop in Terminal?

A for loop iterates through files matching a glob pattern and applies mv to each one. The syntax for f in *.jpg; do mv "$f" "photo_$f"; doneadds the prefix "photo_" to every JPEG file in the current directory. This approach handles basic batch renames without installing additional tools.

The glob pattern after in determines which files the loop processes. The pattern *.jpg matches all JPEG files. The pattern IMG_*.pngmatches PNG files starting with "IMG_" and the pattern * matches every file in the directory. Each iteration assigns the current filename to the variable $f which you reference inside the do ... done block.

Parameter expansion transforms filenames within the loop without external tools. The expression ${f%.jpg}.png strips the .jpg extension and appends .pnginstead, which effectively changes every file's extension. The expression ${f#IMG_}removes the prefix "IMG_" from the beginning of each filename. These expansions are built into Bash and execute faster than piping through sed or awk.

A counter variable inside the loop adds sequential numbers to filenames. Initialize the counter with i=1 before the loop, use mv "$f" "photo_$i.jpg" inside the loop body, and increment with ((i++)) after each rename. Zero padding requires printf formatting: mv "$f" "$(printf 'photo_%03d.jpg' $i)" produces filenames like photo_001.jpg, photo_002.jpg, and photo_003.jpg.

How Do You Use the rename Utility for Regex Renaming?

The rename utility accepts Perl regular expressions to transform filenames in bulk. Install it with brew install rename through Homebrew. The command rename 's/IMG_(\d+)/Photo_$1/' *.jpg uses a capture group to restructure filenames while preserving the numeric portion.

Homebrew must be installed before you can use the rename utility. Visit brew.sh to install Homebrew if you have not done so already, then run brew install rename in Terminal. The installation adds the rename command to your PATH and makes it available in every Terminal session.

The renamesyntax follows Perl's substitution operator: s/pattern/replacement/flags. The pattern uses full Perl regex syntax including character classes like \d for digits, \w for word characters, and quantifiers like + and *. Capture groups enclosed in parentheses store matched text for use in the replacement string as $1, $2, and so on. The g flag applies the replacement to every occurrence within the filename rather than just the first match.

The -n flag runs a dry run that prints the proposed renames without executing them. Always run rename -n 's/pattern/replacement/' *.ext first to verify the output before committing. The -v flag enables verbose mode, which prints each rename as it happens. Batchio's find and replace with regex support provides the same Perl regex power in a visual interface where every change appears in a live preview before you commit.

Can You Add Prefixes or Suffixes to Files in Terminal?

Terminal adds prefixes using for f in *; do mv "$f" "prefix_$f"; done and suffixes using parameter expansion to insert text before the file extension. The rename utility handles both operations with regex: rename 's/^/prefix_/' * for prefixes and rename 's/(\.\w+)$/_suffix$1/' * for suffixes.

Prefix addition is the simplest batch operation in Terminal because string concatenation places the new text before the variable. The command for f in *.pdf; do mv "$f" "2026_$f"; done adds the year prefix to every PDF file. The rename equivalent is rename 's/^/2026_/' *.pdf where the caret ^ anchors the match to the start of the filename.

Suffix addition requires more care because the new text must appear before the extension rather than after it. Parameter expansion handles this cleanly: for f in *.jpg; do mv "$f" "${f%.jpg}_edited.jpg"; done strips the extension, appends the suffix, and reattaches the extension. The rename approach uses a capture group: rename 's/(\.\w+)$/_edited$1/' *.jpg captures the extension and places the suffix before it.

Date based prefixes are common for organizing files chronologically. The command for f in *.png; do mv "$f" "$(date +%Y-%m-%d)_$f"; doneprepends today's date to every PNG file. For more complex date patterns or metadata based dates, see the regex file renaming guide which covers advanced pattern construction.

How Do You Remove Characters from Filenames in Terminal?

Terminal removes characters from filenames using parameter expansion, sed, or the rename utility. Parameter expansion like ${f// /} strips all spaces from a filename. The command rename 's/[^a-zA-Z0-9._-]//g' * removes every character that is not a letter, digit, dot, underscore, or hyphen.

Parameter expansion provides the fastest method for removing specific characters without external tools. The syntax ${variable//pattern/replacement}performs global substitution within the variable's value. Setting the replacement to empty effectively deletes every match. The command for f in *; do mv "$f" "${f// /_}"; done replaces all spaces with underscores in every filename in the current directory.

The tr command translates or deletes characters from a string piped through it. The command for f in *; do mv "$f" "$(echo "$f" | tr -d ' ')"; done deletes all spaces from filenames by piping each name through tr with the delete flag. The tr command works on single characters only and cannot match multi character patterns or regular expressions.

The rename utility handles complex character removal with regex. The command rename 's/\s+/_/g' * replaces all whitespace sequences with a single underscore. The command rename 's/[()]//g' * strips parentheses and curly braces from every filename. For bulk character removal across large file collections, Batchio's batch rename files on Mac approach provides a dedicated remove characters rule with checkboxes for common character categories.

What Are the Limitations of Terminal File Renaming?

Terminal file renaming has no live preview, no built in undo, and high error potential from typos in commands. A single misplaced character in a regex pattern can corrupt hundreds of filenames instantly. Terminal also requires memorizing command syntax and has no visual feedback until after the rename executes.

The absence of a preview is the most significant limitation. The rename utility's -n dry run flag helps, but mv commands in for loops have no equivalent. You must visually parse the command and mentally simulate its effect on every filename. Complex parameter expansions and nested substitutions make this mental simulation unreliable for large batches.

Terminal provides no undo mechanism for file renames. Once mv executes, the original filename is gone. Recovering requires either running a reversal command, restoring from Time Machine, or recreating the original names manually. Accidental overwrites caused by naming collisions are permanent because mv replaces existing files silently unless you remembered the -i or -n flag.

Batchio's live previewsolves every limitation of Terminal renaming. The two column view shows original names on the left and new names on the right, with changed portions highlighted. Conflict detection warns you before any files would overwrite each other. Full undo support stores up to 100 rename operations in history, so you can revert any mistake with Cmd+Z. For users who need Terminal's regex power without Terminal's risks, Batchio provides the best of both approaches in a native macOS interface.

Frequently Asked Questions

Does the mv command work on hidden files in Terminal?
The mv command works on hidden files when you reference them by their full name including the leading dot. A command like mv .config .old_config renames the hidden file directly. Glob patterns like *.txt do not match hidden files by default. You need to enable dotglob with shopt -s dotglob or reference hidden files explicitly.
How do you undo a rename in Terminal on Mac?
Terminal has no built in undo for file renames. You must run a second mv command to reverse the change manually. For batch renames, you need a reversal script that maps each new name back to its original name. Keeping a log of the original filenames before running a batch rename is the safest approach.
Can you rename files recursively in subdirectories from Terminal?
The find command paired with exec or xargs renames files recursively. A command like find . -name '*.txt' -exec rename 's/old/new/' {} + applies a rename pattern to every matching file in every subdirectory. Be cautious with recursive renames because they affect files you may not have reviewed individually.
What is the difference between mv and rename on Mac Terminal?
The mv command is a built in macOS utility that moves or renames a single file per invocation. The rename utility is a Perl script installed through Homebrew that accepts regular expressions and operates on multiple files at once. Use mv for simple single file renames and rename for batch operations that require pattern matching.
Is there a safe way to preview Terminal renames before executing them?
The rename utility supports a -n (dry run) flag that prints what would happen without actually renaming any files. The mv command has no equivalent preview flag. For mv based loops, you can replace mv with echo mv to print the commands instead of running them. Batchio provides a real time live preview that shows every filename change before you commit.

Terminal Power, Visual Safety

Batchio gives you full regex support with a live preview that shows every change before you commit. No more blind renames. Free on the Mac App Store.

Coming Soon to the Mac App Store
Marcel Iseli
Marcel Iseli

Creator of Batchio · Indie App Developer

LinkedIn ↗

Marcel Iseli is an indie app developer and the creator of Batchio. He builds native macOS utilities focused on productivity and file management, with a focus on lightweight, subscription-free tools.