How to replace spaces in all file names with underscore in Linux using shell script?
Solution 1
Use this with bash
:
find $1 -name "* *.xml" -type f -print0 | \
while read -d $'\0' f; do mv -v "$f" "${f// /_}"; done
find
will search for files with a space in the name. The filenames will be printed with a nullbyte (-print0
) as delimiter to also cope with special filenames.
Then the read
builtin reads the filenames delimited by the nullbyte and finally mv
replaces the spaces with an underscore.
EDIT: If you want to remove the spaces in the directories too, it's a bit more complicated. The directories are renamed and then not anymore accessible by the name find
finds. Try this:
find -name "* *" -print0 | sort -rz | \
while read -d $'\0' f; do mv -v "$f" "$(dirname "$f")/$(basename "${f// /_}")"; done
The sort -rz
reverses the file order, so that the deepest files in a folder are the first to move and the folder itself will be the last one. So, there are never folders renamed before all files and folder are rename inside of it. The mv
command in the loop is a bit changed too. In the target name, we only remove the spaces in the basename of the file, else it wouldn't be accessible.
Solution 2
Using
rename
find . -type f -name "* *.xml" -exec rename "s/\s/_/g" {} \;
or with
$1
find "$1" -type f -name "* *.xml" -exec rename "s/\s/_/g" {} \;
Using
mv
find . -type f -name "* *.xml" -exec bash -c 'mv "$0" "${0// /_}"' {} \;
or with
$1
find "$1" -type f -name "* *.xml" -exec bash -c 'mv "$0" "${0// /_}"' {} \;
Solution 3
This is a method I found while facing the same problem:
for f in *; do mv "$f" `echo $f | tr ' ' '_'`; done
I was writing a bash script file to automatically update my ssl certificates.
Solution 4
Use rename
:
rename 's/\s/_/g' ./*.xml
No need for find
:)
Related videos on Youtube
krishna
Updated on September 18, 2022Comments
-
krishna over 1 year
I tried following shell script which should replace spaces from all xml filenames
for xml_file in $(find $1 -name "* .xml" -type f); do echo "removing spaces from XML file:" $xml_file mv "$xml_file" "${xml_file// /_}"; done
Suppose, I have xml file with the name
xy z.xml
, then it gives:removing spaces from XML file: /home/krishna/test/xy mv: cannot stat `/home/krishna/test/xy': No such file or directory removing spaces from XML file: .xml mv: cannot stat `z.xml': No such file or directory
-
krishna almost 9 yearsI don't know why but your given command is not working for me. It is not showing any error and output.
-
A.B. almost 9 years@krishna corrected, sorry
-
krishna almost 9 yearsI am trying to replace spaces with underscore in all directory but it is giving error because after changing name that directory is not accessible.
-
chaos almost 9 years@krishna I added an edit to my answer.
-
somethingSomething almost 6 years@chaos wow, just ran these two on two systems and it worked like a charm, few files and dirs not going through but it's only a few
-
Brian Piercy over 4 yearsRename worked for me. Fistbump!
-
Laszlo Pinter over 4 yearsOn macOS we need to specify the directory in the find command before the -name option
find . -name "* *" -print0 | sort -rz | \ while read -d $'\0' f; do mv -v "$f" "$(dirname "$f")/$(basename "${f// /_}")"; done
-
jbrahy over 4 yearsadd the trailing g to the regex and it works perfectly. 's/\s/_/g'
-
Jan Werkhoven over 4 yearsGood tip, thanks :)
-
alper over 3 yearsthis makes corruption in the zsh history file
-
Admin almost 2 yearsCould this solution applied to remove a specific patterns from the file name like
-_-
?