26

I named a number of files with spaces in them, and I want to replace the space with _. However, every time I write a command in the shell with the file name (eg Spring 2011), the shell doesn't recognize the file or directory.

What can I do about this? Is there any way to use the unicode character for a space?

migrated from stackoverflow.com Jun 12 '11 at 3:35

This question came from our site for professional and enthusiast programmers.

32

Escape the space, e.g. Spring\ 2011, or use quotes, e.g. 'Spring 2011'. In the future, it's typically a bad idea to use file names with spaces in them on any *NIX.

If you've got rename, you can use this:

rename ' ' '_' [filenames...]
  • 1
    Do you know is there anyway to do this for all the files at once? – Phil Braun Jun 8 '11 at 19:55
  • @phil for the rename command, specify a pattern for filenames that matches all the files you want to rename (e.g. if there's a common prefix/suffix). – Rafe Kettler Jun 8 '11 at 20:04
  • 3
    Why is it a bad idea? It's the responsibility of the programmer to handle filenames properly. – glenn jackman Jun 9 '11 at 14:28
  • 1
    @rafe, really it's error prone not to handle filenames properly up front. The extra effort comes when having to debug a script when you simply forgot to quote variables containing a filename. – glenn jackman Jun 9 '11 at 15:52
  • 3
    This answer does not seem to work (on Ubuntu 12.04 LTS, at least). The answer from unutbu works fine though. – DNA Sep 3 '12 at 14:44
29

If your machine has the rename command, then this will change all spaces to underscores in all files/dirs in the current working directory:

rename 's/ /_/g' *
  • Confirmed to work in Ubuntu 12.04 – anthonygore Oct 10 '14 at 6:50
  • 1
    didn't work for me... i got an error of "rename: not enough arguments". i have version rename --version rename from util-linux 2.23.2. – Trevor Boyd Smith Oct 5 '18 at 14:12
23

If you don't have rename or prefer to use just the shell:

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

Broken down:

  • *\ * selects all files with a space in their name as input for the the for loop.
  • The quotes around "$f" are important because we know there's a space in the filename and otherwise it would appear as 2+ arguments to mv.
  • ${f//str/new_str} is a bash-specific string substitution feature. All instances of str are replaced with new_str.
  • 2
    this works but for me it only replaces the first space. if i use for f in *\ *; do mv "$f" "${f// /_}"; done it works – billynoah Jul 7 '14 at 21:52
  • @billynoah Good catch, updated. – blahdiblah Jul 7 '14 at 22:05
  • @blahdiblah Thank you so much! You just saved me so much time! – Guerrilla Feb 20 '16 at 17:03
  • @blahdiblah your solution is way way more elegant than my solution. good job. I didn't think the for loop glob would work... so i did the glob outside of the for loop. – Trevor Boyd Smith Oct 3 '18 at 17:58
3

mv "Spring 2011.file" Spring_2011.file should tell the command-line to take the quoted string as a single input.

  • This is the only answer that I could get to work. – blakeoft Jan 20 '15 at 22:00
0

To programmatically rename N files, you can use a simple bash for loop.

#!/bin/bash

set -eux

# find all your files by using a `grep` pattern
pattern="insert_filename_pattern_here" # you must enter your filename pattern here

# create an array of filenames and split on newlines
IFS=$'\n'
tmp=($(ls | grep ${pattern}))
unset IFS

# for each filename
for filename in "${tmp[@]}"; do
    # rename the filename to use "_" character instead of a " " character
    mv -v "${filename}" "${filename// /_}"
done

If you have less than 5 filenames, then you can manually type in all the filenames and use the rename command like the above solution suggests. But for me... I prefer the programmatic solution... even when there is only 4 files.

p.s.

if you aren't familiar with Bash's Parameter Expansion (i.e. ${filename// /_}) you could use the rename command:

if ((0)); then
    mv -v "${filename}" "${filename// /_}"
else
    rename ' ' '_' "${filename}"
fi

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