Dealing With Spaces in File Names in Command-line (GNU/Linux)

Most people that use GNU/Linux do not like to deal with the command-line at all, though having a basic understanding of it (such as memorizing commands for mouting devices and copying files for instance) can come in real handy sometimes.

That said however, when dealing with files under command-line, say that you had to use it to backup your data because the desktop session was not working anymore, it is pretty common that one should come across files that contain spaces in their names. And unless you are aware of this simple trick, it can be quite frustrating, because for each space you have to add a backslash ( \ ) when using the command-line.

For example, let us assume that I have a file called Data backup 2.tar on my Home folder, and that I need to copy it to /media/pen location using the ‘cp’ command. If I enter the below command then I will receive an error saying that there exists no such file/directory.

sudo cp Data backup 2.tar /media/pen

'cp' giving errors while copying a file name that contain spaces - Ubuntu 13.10

Note: I am running ‘cp’ with ‘sudo’ (administrative) privileges.

In fact, if you carefully look at the output, you can see that command-line has treated the file name as three different files due to the three spaces that are present in the file name. So how can we overcome this ?

Well, you can add backslashes as mentioned before and below is the correct command using that.

sudo cp Data\ backup\ 2.tar /media/pen

But as you can see, not only it is time consuming, but since we are not that used to seeing backslashes on file names, it can be really confusing as well. So instead, you can put the file name that contains spaces, between two apostrophes. For this example, I will use the below command and the copying will be carried on without errors.

sudo cp 'Data backup 2.tar' /media/pen

Successfully copying a file that contains spaces in its name using 'cp' - Ubuntu 13.10

As you see, once you add the first apostrophe, then you can type the file name freely, and when done entering the name, make sure to add another apostrophe (this is very important). That is all there is to it.

If a path contains two or more file names with spaces …

You can do the same. You can add apostrophes separately to each name, or you can put that particular path which contains names with spaces, between two apostrophes, as a whole, which is much easier. Coming back to the above example, let us say the Data backup 2.tar file is inside a folder called untitled folder that is located on my Home folder, then I will use the below command for copying it to the same destination.

sudo cp 'untitled folder/Data backup 2.tar' /media/pen

If both file paths (source and destination) contain such names (or even a mix -- a file path that contains names with spaces and names without them), then you can add apostrophe pairs to each path, separately. Let us take the same example and say that this time we need to copy it over to /media/pen 2/new folder (as you can see this path contains two names with spaces in their names and one without). 

For that I will use the below command.

sudo cp 'untitled folder/Data backup 2.tar' '/media/pen 2/new folder'

(Again, please remember that I have used ‘sudo’ with ‘cp’ because I am copying files to a location which requires administrative privileges. Here I have also colored the apostrophe pairs differently so it is easy to understand).

But the rule is, no matter what you do, you should treat the two paths (file source and the destination) individually. In other words, you cannot put the whole command (two file paths) inside two apostrophes, if you do so, then ‘cp’ will treat it as a the file source and will give an error saying the destination is missing.

sudo cp 'untitled folder/Data backup 2.tar /media/pen 2/new folder'

I’ve cropped out some of the output in the image. If you’re interested, the error says: ‘cp’: missing destination file operand after /untitled folder/Data backup 2.tar /media/pen 2/new folder0 (edit: 0 is an error code).

To finish, not just with ‘cp’, you can use this trick with almost any command that requires you to deal with a file name that contain spaces under the command-line in GNU/Linux. Good luck.

22 thoughts on “Dealing With Spaces in File Names in Command-line (GNU/Linux)

  1. Very informative. Wondering if this single quote thing works everywhere in Linux, or just dealing with the file system? Reason is that I need to issue some networking commands, one being “set wlan ssid xxxx” where the xxxx is the name of my Wi-Fi network ID. Unfortunately, when I created this network name five years ago I did not realize that spaces were frowned upon and went merrily on my way. Unfortunately #2 is that changing it could be ugly. Can I use the single quotes in this command type of setting?

    Thanks, Jim

  2. i am facing a strange issue here, instances imported from oracle are copied with spaces and ? in between them:
    # ll
    total 6536
    -rw-r–r– 1 oracle dba 363382 Sep 7 17:13 Ordering 9.3?HF04?Release Notes.docx
    -rw-r–r– 1 oracle dba 460073 Sep 15 17:07 Ordering 9.3?HF05?Release Notes.docx
    -rw-r–r– 1 oracle dba 803259 Sep 21 20:02 Ordering 9.3_HF6_Release Notes.docx
    -rw-r–r– 1 oracle dba 398146 Sep 21 15:55 Ordering 9.3?HF6?Release Notes.docx

    When tried to copy the file or rename it it is not able to search it:
    [root@illin629 hf_rn_files]# cp ‘Ordering 9.3?HF04?Release Notes.docx’ ‘Ordering 9.3_HF04_Release Notes.docx’
    cp: cannot stat `Ordering 9.3?HF04?Release Notes.docx’: No such file or directory

    [root@illin629 hf_rn_files]# cp ‘Ordering 9.3?HF04?Release Notes.docx’ Ordering_9.3_HF04_Release Notes.docx
    cp: target `Notes.docx’ is not a directory

    Please help me here…..

  3. Hi,
    How about when you try to cp files in a loop? for instance:
    for x in `ls hello\ world*`; do cp $x $x-new; done
    cp: cannot stat `$x’: No such file or directory
    cp: cannot stat `$x’: No such file or directory
    I’m searching in google, but with no satisfatory answer yet. Please help.

    • Hi Alexis,

      First of all, please remember that I’m not a hard shell scripter. That said, the solution to your problem can be found through use of Internal Field Separator (IFS) which as the name suggest is what Bash uses for recognizing how a field is defined. By default, a field is defined by IFS by a space which is also why the file copy loop fails as the file’s full name does not get recognized because as soon as its first space is reached, Bash considers its the end of the line/field.

      So the solution is simple. We simply have to say to IFS that a field of text should not be considered full, even if it contains spaces, until the ‘newline’ (the actual end of a field of text) is reached. And below is the command for that:

      IFS="$(printf '\n\t')"

      Once that’s done, the loop should continue without errors (yes I tested it). So the command (or script) that you should be using is the below one:

      IFS="$(printf '\n\t')"; for x in `ls hello\ world/*`; do cp $x $x-new; done; unset IFS

      You can read more about Internal Variables from the below link:

      P.S (once opened, search for ‘IFS’ in your web browser). I hope this was helpful.

    • @Alexis Cardoso:

      Gayan’s tip below is useful to know, but I wanted to add to it. You shouldn’t use `ls` to get a list of files in Bash script. Just use the built-in filename expansion (aka “globbing”); for instance:

      for x in *somestring*; do cp $x $x-new; done

      The reason for this is that the `ls` call can produce more than just a list of file names, such as if there’s no match. If the glob returns nothing (i.e. no match), the for loop will just exit immediately and have no effect. This is a common mistake, and everyone makes it at first, until they understand globbing. Technically, when you call `ls *somestring*`, Bash expands the *somestring* part to be all matching file names, then passes the list of matches to `ls`. Bash did all the name-matching work, not `ls`.

  4. Thank you Gayan for giving a helping hand to those who have found Linux!

    Please allow me to toss in 2 cents on Linux file names from a little different direction.

    This took place some twelve to fifteen years ago while using a backup program. I discovered that the spaces in the file names was a villain when using most backup programs at that time. They would not backup filenames that had more than two to three spaces in the name.

    From that day to this I fill most of those spaces with “.”, but will use these also: “-“, “_”, “%”.
    There are a few other characters that are legal but these have save my bacon 99% of the time!

    Thanks again Gayan!

  5. Thanks Gayan, this solved my inline script using imagemagick to resize photos. I put quotes round the source filter… ‘*.jpg’ …which allowed the interpreter to act on filenames with spaces, but I couldn’t get the renamed file to work. In this case, using IFS cured it so I could do stuff like
    IFS=”$(printf ‘\n\t’)”; for i in *.jpg; do convert $i -resize 50% small-$i; done
    This (after installing imagemagick!) will resize all jpg files to half size and append “small-” to the filename. ImageMagick has loads of variations on that, by the way.

  6. Thank you ! I tried just about everything and nothing worked !
    But robocopy was successful and not difficult to do at all !
    I recommend this over LONG PATH TOOL and it’s free.

  7. Very interesting. I am completely new to linux and just using it to do SSH login and file management on my NAS drive. I wondered how you deal with recursive directories and files with spaces in? My NAS stores huge numbers of directories and files created in Windows, many of them nested several deep, and I obviously don’t want to either rename them all or put their paths in inverted commas. Any suggestions?

Leave a Comment