Search code examples
bashspacefile-renameunderline

simple bash script to change spaces to underlines in a file name


mv $1 $(echo $1 | sed s:\ :_:g)

It's a simple script that renames the file passed as argument, exchanging spaces to underlines. However, when I try to rename the file "a e i" to "a_e_i" for example, it returns the following error:

./spc2und a\ e\ i 
mv: target `a_e_i' is not a directory

Solution

  • You need double-quotes around the variables and command substitution to prevent spaces in the filename from being mistaken for argument separators. Also, you don't need sed, since bash can do character replacement by itself:

    mv "$1" "${1// /_}"
    

    Edit: a few more things occurred to me. First, you really should use mv -i in case there's already a file with underscores ("a_e_i" or whatever). Second, this only works on simple filenames -- if you give it a file path with spaces in an enclosing directory, (e.g. "foo bar/baz quux/a e i"), it tries to rename it into a directory with the spaces converted, which doesn't exist, leading to comedy. So here's a proposed better version:

    mv -i "$1" "$(dirname "$1")/$(basename "${1// /_}")"
    

    BTW, the other answers leave off the double-quotes on the filename after replacing spaces with underscores -- this isn't entirely safe, as there are other funny characters that might still cause trouble. Rule 1: when in doubt, wrap it in double-quotes for safety. Rule 2: be in doubt.