Skip to content
Go back

Remove spaces or Edit chracters in filenames

· Updated:
By SumGuy 6 min read
Remove spaces or Edit chracters in filenames

Needed  to remove spaces from filenames, so here we are 🙂

for file in *.mp3; do mv "$file" `echo $file | sed -e 's/  */_/g' -e 's/_-_/-/g'`; done

or replace all spaces by _ using perl

ls *.bed |perl -ne 'use File::Copy;chomp;$old=$_;s/\s+/_/g;move($old,$_);'

remove underscores

rename 's/2012mp3/2012/' *.mp3

Remove the letters mp3 from middle fo filename say in case of 123-20121mp3.mp3 or some such

for i in *.mp3; do mv $i ${i//[[:punct:]]/}; done

remove punctuations from filename. WARNING it will also remove the . from extension names.

for foobar in *.mp3 ; do
temp=`echo "$foobar" | cut -c 2-`
mv "$foobar" "$temp" ;
done

remove first X characters from file name. change the 2 to any number to change the first characters removed. the formula for that is 1 + actual number. make sure to change the extension.

rename 's/1234/12-34/' *.mp3

remove some character from the middle of the file name, in this case the dash ( – ).

When Things Go Sideways

That punctuation removal one-liner up there? It’ll nuke your file extension too. You lose track01.mp3 and get track01mp3 — a useless blob your media player won’t touch. The fix is either being surgical about what you strip, or reconstructing the extension afterward. Surgical is easier:

Terminal window
# Strip punctuation from the base name only, leave the extension alone
for f in *.mp3; do
base="${f%.*}"
ext="${f##*.}"
clean="${base//[[:punct:]]/}"
mv "$f" "${clean}.${ext}"
done

The ${f%.*} strips everything after the last dot (the extension). ${f##*.} grabs just the extension. You glue them back together. Simple, doesn’t blow up your files.

The rename Command Has Two Different Versions

This trips people up constantly. rename 's/foo/bar/' *.mp3 works fine on Debian/Ubuntu where rename is the Perl-based File::Rename. On Red Hat/Arch/Fedora it’s rename from to files — a completely different syntax with no regex support.

Terminal window
# Check which one you have
rename --version
# Perl version says: /usr/bin/rename using File::Rename version X.XX
# util-linux version says: rename from to file...

If you’re on the util-linux version and need regex, either install perl-rename (some distros package it that way) or just write the bash loop. The bash loop always works. Everywhere.

Bulk Cleanup for Mixed Filenames

Real world scenario: you’ve downloaded a folder of files that have spaces, parentheses, weird unicode dashes, and numbers in the name. One pass of sed won’t cut it. Here’s a chained approach that handles most of the mess in one shot:

Terminal window
for f in *; do
[ -f "$f" ] || continue # skip directories
newname=$(echo "$f" \
| sed 's/ /_/g' \
| sed 's/[(){}]//g' \
| sed 's/\[//g; s/\]//g' \
| sed 's/--*/-/g' \
| sed 's/__*/_/g')
[ "$f" != "$newname" ] && mv -- "$f" "$newname"
done

The [ -f "$f" ] || continue guard matters — without it you’ll try to mv directories too. The [ "$f" != "$newname" ] check skips files that didn’t need renaming, so you don’t get a wall of redundant mv calls cluttering your terminal.

Dry Run First, Always

Before running any bulk rename on a directory you care about, swap the mv for echo and see what would happen:

Terminal window
for file in *.mp3; do
newname=$(echo "$file" | sed -e 's/ */_/g' -e 's/_-_/-/g')
echo "mv \"$file\" \"$newname\""
done

You’re just printing the commands instead of running them. If the output looks wrong, you’ve saved yourself a recovery session. If it looks right, remove the echo and run for real. Your 2 AM self will appreciate not having to fish files out of the trash.

Unicode and Special Characters

If your filenames came from Windows, macOS, or some ancient MP3 downloader, you might have em-dashes (), en-dashes (), or non-breaking spaces mixed in that look identical to regular dashes and spaces in your terminal but aren’t. sed 's/ /_/g' won’t touch them.

Terminal window
# Nuke anything that isn't alphanumeric, dot, dash, or underscore
for f in *; do
[ -f "$f" ] || continue
newname=$(echo "$f" | tr -dc 'a-zA-Z0-9._-' | sed 's/--*/-/g')
[ "$f" != "$newname" ] && mv -- "$f" "$newname"
done

tr -dc 'a-zA-Z0-9._-' deletes every character that isn’t in that set. It’s a blunt instrument — you lose accented characters too — but for filenames going into a script or a web server, boring ASCII is exactly what you want.

When the Target File Already Exists

One scenario that bites people more than it should: you run your rename loop and halfway through it errors out because the destination filename already exists. Say you’ve got Track 01.mp3 and Track_01.mp3 sitting in the same folder — after normalizing spaces to underscores, both want to be Track_01.mp3. The second mv just silently overwrites the first on most systems.

Terminal window
# Safe rename loop that skips collisions instead of overwriting
for file in *.mp3; do
newname=$(echo "$file" | sed -e 's/ */_/g' -e 's/_-_/-/g')
if [ "$file" = "$newname" ]; then
continue # nothing to rename
fi
if [ -e "$newname" ]; then
echo "SKIP: '$newname' already exists (would overwrite '$file')"
continue
fi
mv -- "$file" "$newname"
done

The [ -e "$newname" ] check catches the collision before mv does something regrettable. You get a log of what was skipped, and you can decide manually — keep one, merge them, or rename to Track_01_b.mp3. Either way, you’re not losing data silently.

If you want automatic deduplication — say you’re certain the duplicate content is identical — you can skip both files and deal with them later, or generate a unique suffix on the fly:

Terminal window
# Auto-suffix collisions: Track_01.mp3 → Track_01_1.mp3, Track_01_2.mp3, etc.
counter=1
while [ -e "${newname%.*}_${counter}.${newname##*.}" ]; do
((counter++))
done
newname="${newname%.*}_${counter}.${newname##*.}"
mv -- "$file" "$newname"

Clunky, but better than a mystery missing file at 2 AM.


Share this post on:

Send a Webmention

Written about this post on your own site? Send a webmention and it'll show up above once verified.


Previous Post
Proxy Chains and Anonymization: What Actually Works and What's Just Theater
Next Post
Repair & Optimize all Mysql Databases one liner

Discussion

Powered by Garrul . Sign in with GitHub or Google, or post anonymously.

Related Posts