128

I have a number of files in a folder, and I want to replace every space character in all file names with underscores. How can I achieve this?

11 Answers 11

221

This should do it:

for file in *; do mv "$file" `echo $file | tr ' ' '_'` ; done
3
  • This didn't work for me. It claimed identical files existed (with the wrong filenames). E.g. trying to rename 1 - foo.jpg and my folder already had 1.jpg in it.
    – byxor
    Commented Oct 18, 2017 at 14:05
  • 9
    I find backticks bit hard to read when they are near quotes. The same but more readable would be for file in *; do mv "$file" $(echo $file | tr ' ' '_') ; done Commented Jul 3, 2018 at 8:58
  • Note: This is run from WITHIN the directory whose files' names you want to update. Alternatively, you can change * to PATH_TO_YOUR_DIRECTORY.
    – CFitz
    Commented Mar 8, 2019 at 20:06
94

I prefer to use the command 'rename', which takes Perl-style regexes:

rename "s/ /_/g" *

You can do a dry run with the -n flag:

rename -n "s/ /_/g" *
9
  • 3
    this will work if you have the perl-style rename and not the simpler redhat/fedora one
    – David Dean
    Commented Nov 27, 2009 at 5:56
  • 10
    the fedora version would be rename " " "_" *
    – David Dean
    Commented Nov 27, 2009 at 5:57
  • 5
    rename not available in OSX it appears. Commented Feb 12, 2014 at 16:53
  • On macOS 10.12.3, rename is available.
    – mc9
    Commented Mar 14, 2017 at 6:09
  • 1
    @DavidDean The rename on Arch Linux will only replace the first occurrence (not very convenient for files/directories with multiple spaces). It has the same syntax as the fedora one, so I suspect they may be the same one. But perl-rename can be installed.
    – prosoitos
    Commented Apr 29, 2019 at 14:42
20

Use sh...

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

If you want to try this out before pulling the trigger just change mv to echo mv.

0
6

What if you want to apply the replace task recursively? How would you do that?

Well, I just found the answer myself. Not the most elegant solution, (also tries to rename files that do not comply with the condition) but it works. (BTW, in my case I needed to rename the files with '%20', not with an underscore)

#!/bin/bash
find . -type d | while read N
do
     (
           cd "$N"
           if test "$?" = "0"
           then
               for file in *; do mv "$file" ${file// /%20}; done
           fi
     )
done
0
5

If you use bash:

for file in *; do mv "$file" ${file// /_}; done
2
  • when i tried, i got mv: when moving multiple files, last argument must be a directory Try mv --help' for more information. mv: when moving multiple files, last argument must be a directory Try mv --help' for more information. Commented Nov 27, 2009 at 5:32
  • Again error mv: missing file argument Try mv --help' for more information. mv: missing file argument Try mv --help' for more information. mv: missing file argument Try mv --help' for more information. mv: missing file argument Try mv --help' for more information. Commented Nov 27, 2009 at 7:07
4

Here is another solution:

ls | awk '{printf("\"%s\"\n", $0)}' | sed 'p; s/\ /_/g' | xargs -n2 mv
  1. uses awk to add quotes around the name of the file
  2. uses sed to replace space with underscores; prints the original name with quotes(from awk); then the substituted name
  3. xargs takes 2 lines at a time and passes it to mv
2

Try something like this, assuming all of your files were .txt's:

for files in *.txt; do mv “$files” `echo $files | tr ‘ ‘ ‘_’`; done
2
  • 2
    got the below error tr: two strings must be given when translating mv: missing file argument Try `mv --help' for more information. Commented Nov 27, 2009 at 5:31
  • 2
    Agin error tr: too many arguments Try tr --help' for more information. mv: missing file argument Try mv --help' for more information. Commented Nov 27, 2009 at 7:06
1

Quote your variables:

for file in *; do echo mv "'$file'" "${file// /_}"; done

Remove the "echo" to do the actual rename.

3
  • It is echoing the mv commands prperly, but not really renaming the file! Commented Nov 27, 2009 at 7:05
  • removing echo produces error like mv: cannot stat \'1130 lake micigan view.jpg\'': No such file or directory mv: cannot stat \'1130_1_bedroom_floor_plan.jpg\'': No such file or directory mv: cannot stat \'1130_BedPicture_8.jpg\'': No such file or directory mv: cannot stat \'1130_diningroom_table.jpg\'': No such file or directory Commented Nov 27, 2009 at 7:08
  • Linux Linux 2.6.9-42.0.3.EL.wh1smp #1 SMP Fri Aug 14 15:48:17 MDT 2009 i686 i686 i386 GNU/Linux Commented Nov 27, 2009 at 11:54
1

To rename all the files with a .py extension use, find . -iname "*.py" -type f | xargs -I% rename "s/ /_/g" "%"

Sample output,

$ find . -iname "*.py" -type f                                                     
./Sample File.py
./Sample/Sample File.py
$ find . -iname "*.py" -type f | xargs -I% rename "s/ /_/g" "%"
$ find . -iname "*.py" -type f                                                     
./Sample/Sample_File.py
./Sample_File.py
1
  • By far this is the only solution that worked on mac/zsh based terminal.
    – VanagaS
    Commented Mar 17, 2023 at 21:52
0

This will replace ' ' with '_' in every folder and file name recursivelly in Linux with Python >= 3.5. Change path_to_your_folder with your path.

Only list files and folders:

python -c "import glob;[print(x) for x in glob.glob('path_to_your_folder/**', recursive=True)]"

Replace ' ' with '_' in every folder and file name

python -c "import os;import glob;[os.rename(x,x.replace(' ','_')) for x in glob.glob('path_to_your_folder/**', recursive=True)]"

With Python < 3.5, you can install glob2

pip install glob2
python -c "import os;import glob2;[os.rename(x,x.replace(' ','_')) for x in glob2.glob('path_to_your_folder/**')]"
1
  • this didn't work for subfolders which had spaces in them Commented Apr 1, 2021 at 2:11
-1

The easiest way to replace a string (space character in your case) with another string in Linux is using sed. You can do it as follows

sed -i 's/\s/_/g' *

Hope this helps.

1
  • This does not address the question.
    – amit kumar
    Commented Apr 19, 2020 at 8:36

Not the answer you're looking for? Browse other questions tagged or ask your own question.