1. Overview
Often, as Linux users, we find ourselves in a bit of trouble when some of the file commands or applications are rendered inoperative due to a space in a filename. Certain file operations or practices like saving files with space in the filename can be a probable cause. In this article, we’ll discuss some of the plausible ways to rename such files by replacing space(s) from the filename.
2. Single mv Command
The Linux mv command does not always successfully move or rename a file or directory. In fact, when used for replacing spaces from the filename, it returns a No such file or directory message. We’ll discuss three options that make accessing and renaming such files possible.
2.1. Using Backslash or Tab Completion
We can either deliberately place a backslash or hit the tab button right before the space to escape this special character. However, using the tab button is a preferred method as it entails auto-completion of the name. Still, using either of these two methods, we can access the file and rename it using mv. The following example illustrates how:
mv File\ with\ Spaces File_with_Spaces
2.2. Name in Quotes
By simply including the file in double quotes, we can access the file ‘File with Spaces’. The mv command to rename will look like this:
mv "File with Spaces" File_with_Spaces
2.3. Accessing File Using find
One of the marked differences between ls and find is that find can search for files with a space in the name. The search pattern for the find command, in this case, will be “* *”. Whereas, ls command with this search pattern fails.
$ ls "* *"
ls: cannot access * *: No such file or directory
With the find command, a filename with spaces will be printed with a null byte (-print0) as the delimiter. Then, the $0 reads the filename delimited with a null byte, and finally, mv replaces the spaces with an underscore:
find . -type f -name "* *" -print0 -exec bash -c ‘mv "$0" "${0// /_}"’ {} \;
The ${0// /_} part utilizes Bash’s parameter expansion to replace a pattern with another string. The syntax is ${parameter/pattern/string}.
3. Other Commands for Renaming Files
To replace spaces from the filename, we can also use rename, sed, and tr. This time we’ll work on a bunch of files. The set of files are controlled either iteratively using the for loop or accessed through the find command.
3.1. Using rename
A simple rename command (which also takes Perl-style regexes) to replace space with an underscore will look like this:
rename ' ' '_' *
It is also an alternative to Bash’s parameter expansion, which we saw in the previous case. rename with find search for files with a space in the name and replaces all such spaces with an underscore:
find * -type f -name "* *" -exec rename "s/\s/_/g" {} \;
With regex, rename may not work on some systems. One might assume that it’s a system dependency. Actually, it’s not. The command has two versions:
- The “Perl” version, with syntax rename ‘s/^fgh/jkl/’ fgh*
- The util-Linux version, with syntax rename fgh jkl fgh*
There is no regex support for util-Linux. rename with regex works with the “Perl” version and is worth installing if one has “no easy access to it”.
3.2. Using sed
sed, as we know, stands for Stream editor. The most common use of the sed command in Linux is for a substitution or find and replace. We can use sed to replace space(s) from the filename as follows:
for i in *' '*; do mv "$i" `echo $i | sed -e 's/ /_/g'`; done
Here, for will store files with space in the name in the variable i. Then, sed will replace all spaces in a filename with an underscore.
3.3. Using tr
The tr command can perform a basic character replacement operation:
for f in *; do mv "$f" `echo $f | tr ' ' '_'`; done
Here, for stores files with space in the name in variable f. Then, tr replaces all characters from the standard input, the first set with the one from the second set.
4. Conclusion
In this article, we saw some tricks to recognize files with space(s) in the filename. We also discussed how we can avoid bash loops by using rename command. Now, no application will fail to recognize filenames treated with either of these methods.