How to replace spaces in file names using a bash script – Dev

The best answers to the question “How to replace spaces in file names using a bash script” in the category Dev.


Can anyone recommend a safe solution to recursively replace spaces with underscores in file and directory names starting from a given root directory? For example:

$ tree
|-- a dir
|   `-- file with spaces.txt
`-- b dir
    |-- another file with spaces.txt
    `-- yet another file with spaces.pdf


$ tree
|-- a_dir
|   `-- file_with_spaces.txt
`-- b_dir
    |-- another_file_with_spaces.txt
    `-- yet_another_file_with_spaces.pdf


Use rename (aka prename) which is a Perl script which may be on your system already. Do it in two steps:

find . -name "* *" -type d | rename 's/ /_/g'    # do the directories first
find . -name "* *" -type f | rename 's/ /_/g'

Based on J├╝rgen’s answer and able to handle multiple layers of files and directories in a single bound using the “Revision 1.5 1998/12/18 16:16:31 rmb1” version of /usr/bin/rename (a Perl script):

find /tmp/ -depth -name "* *" -execdir rename 's/ /_/g' "{}" \;


I use:

for f in *\ *; do mv "$f" "${f// /_}"; done

Though it’s not recursive, it’s quite fast and simple. I’m sure someone here could update it to be recursive.

The ${f// /_} part utilizes bash’s parameter expansion mechanism to replace a pattern within a parameter with supplied string.
The relevant syntax is ${parameter/pattern/string}. See: or .


you can use detox by Doug Harple

detox -r <folder>


find . -depth -name '* *' \
| while IFS= read -r f ; do mv -i "$f" "$(dirname "$f")/$(basename "$f"|tr ' ' _)" ; done

failed to get it right at first, because I didn’t think of directories.