40

It is said that on Unix and Linux in general, you should avoid having spaces in a filename of a file (ordinary file, dir, link, device file, ...).

But I do that all the time. For a filename with a space inside,

  • In Nautilus, the space character is shown as a space.
  • In Bash terminal, I either use \ to represent a space, or enclose the filename within a pair of double quotes.
  • in some applications's files (Nautilus, not sure if OS will also do so), the filename is written with the space replaced with %20.

Is a space really not allowed in a filename?

How do you use or deal with a space in a filename correctly?

8
  • 24
    It's allowed but it's really, really annoying. There is no reason for it. Don't do it. Commented Aug 3, 2014 at 16:56
  • 3
    You can also create a files named -rf ~ (use touch -- "-rf ~"), but I wouldn't recommend it. Commented Aug 3, 2014 at 20:28
  • 6
    You can do it, it's allowed, like creating a self-destruct script called "cd" but you shouldn't do it. Your file already looks different in 3 different tools, isn't that bad enough?
    – Falco
    Commented Aug 4, 2014 at 7:39
  • 10
    Not everyone shares the opinion that it's really, really annoying. And "There is no reason for it" is so obviously false that it doesn't need refuting. I gave in and learned how to handle spaces properly years ago, and for the most part it's really not a big deal.
    – user20460
    Commented Aug 4, 2014 at 9:41
  • 2
    @snailboat Spaces are a symptom of the real problem which is a lack of standardization. Unix filesystems allow file "names" to nearly unrestricted binary blobs. The only illegal bytes are 0 and 47 (the / separator). Using all 254 remaining bytes opens the door to all manners of unspeakable eldritch "names". Obviously this is insane, but not everyone agrees on what "sane" is, and different characters will break different tools. The intersection of everyone's sanity is quite small.
    – jw013
    Commented Aug 6, 2014 at 1:03

5 Answers 5

58

Spaces, and indeed every character except / and NUL, are allowed in filenames. The recommendation to not use spaces in filenames comes from the danger that they might be misinterpreted by software that poorly supports them. Arguably, such software is buggy. But also arguably, programming languages like shell scripting make it all too easy to write software that breaks when presented with filenames with spaces in them, and these bugs tend to slip through because shell scripts are not often tested by their developers using filenames with spaces in them.

Spaces replaced with %20 is not often seen in filenames. That's mostly used for (web) URLs. Though it's true that %-encoding from URLs sometimes makes its way into filenames, often by accident.

20
  • 7
    It's "URL encoding" or "percent encoding" en.wikipedia.org/wiki/URL_encoding As per that the most appropriate name is probably "URI encoding", but people find url easier to say than U.R.I., so this is a common form of misnomer. Notice the set of reserved characters in URI's is larger than it is for *nix filenames.
    – goldilocks
    Commented Aug 2, 2014 at 15:32
  • 1
    @Tim I don't know that you can specify a NUL character in any command line argument in bash. I tried a few things such as quoting it with Ctrl-V and something like $(echo -e \\0) but it didn't work. The thing is, the reason NUL can't be used in filenames is that it can't be used in C strings (because it's the string terminator) and all the underlying APIs as well as virtually all strings handled by C programs use that format. Since bash is written in C, it might simply have no support at all for any strings with NUL in them. I could be wrong, there might be some obscure way...
    – Celada
    Commented Aug 2, 2014 at 15:58
  • 1
    Sort of depends on the context. String functions generally don't count the final null (or rather, the first null is the end of the string, even if there's stuff after it), so in that sense it has zero length and therefore would be considered empty.
    – goldilocks
    Commented Aug 2, 2014 at 16:38
  • 3
    @Celada of course you can use NUL and bash, you need $'\0'. For example: find . -print0 | while read -d $'\0' f; do echo "$f"; done
    – terdon
    Commented Aug 3, 2014 at 12:48
  • 1
    @goldilocks Do people actually pronounce URL as 'url', roughly rhyming with 'earl'?
    – mrr
    Commented Aug 8, 2014 at 22:52
22

Spaces are allowed in filenames, as you have observed.

If you look at the "most UNIX filesystems" entry in this chart in wikipedia, you'll notice:

  • Any 8-bit character set is allowed. We can subsume 7-bit ASCII under this umbrella too, since it is a subset of various 8-bit sets and is always implemented using 8 bit bytes.

  • The only forbidden characters are / and "null". "Null" refers to a zero byte, but these are not allowed in text data anyway.

However, if you make any use of the shell, you may realize that there are some characters that will create a hassle, most significantly *, which is a POSIX globbing operator.

Depending on how you want to define "hassle", you could include whitespace (spaces, tabs, newlines, etc.) in there, as this creates the need for quoting with "". But this is inevitable, since spaces are allowed, so...

How do you use or deal with a space in a filename correctly?

In a shell/command line context, wrap the filename in single or double quotes (but note they are not the same WRT other issues), or escape the spaces with \, e.g.:

> foo my\ file\ with\ spaces\ in\ the\ name
10
  • 1
    How do you specify NUL character in bash? I want to test it in a filename.
    – Tim
    Commented Aug 2, 2014 at 15:56
  • 1
    You can't. The "execve semantics" refers to the fact that in C (and every other language I'm aware of), text strings are null terminated. The shell is implemented in C. The sneakest thing I could think of is touch $(echo -e "foo\00bar") -- -e processes \0N as an octal value, but it still gets lost somewhere, as that just creates a file named foobar. Of course NULL isn't printable, but I guarantee it's gone from there because of the C string restriction.
    – goldilocks
    Commented Aug 2, 2014 at 16:27
  • "text strings are null terminated" -> To explain further: strings are always stored with a zero byte at the end, which is why it "isn't allowed" in text: If you insert one, you've effectively terminated the string at that point. Eg., foo[NULL]bar would end up as foo for most intents and purposes. The fact that doesn't happen with that echo -e shows the NULL has been pruned out somewhere.
    – goldilocks
    Commented Aug 2, 2014 at 16:30
  • 5
    A vast majority of programming languages do allow null characters in strings. It just happens that the main language that doesn't is C, which Unix is built on — and most Unix shells don't allow null characters in strings either. In any case, @Tim, all Unix interfaces use null-terminated strings, so a null byte is the one thing you cannot ever have in a file name (plus / which is the directory separator and cannot be quoted, so can be in a pathname but not in a filename). Commented Aug 2, 2014 at 18:09
  • 1
    ...but [never mind again]. Not something I would do too often, anyway. To my mind there's no reason for them to be in textual data. I would have corrected that, but it's a comment.
    – goldilocks
    Commented Aug 3, 2014 at 11:14
4

The reason is largely historical - WAY back in the mists of time spaces were not allowed in filenames, so spaces were used as keyword / filename separators. Future shell interpreters had to be reverse-compatible with old scripts, and thus we are stuck with the headache we have today.

Developers of processes that do not need to deal with humans very much can make things much, much easier by dropping spaces altogether. Apple does this, the contents of /System/Library/CoreServices/ contains very few spaces, the programs with spaces are opened on behalf of the user, andWouldLookStrangeIfCamelCased. Similar unix-only paths also avoid spaces.

( somewhat related anecdote: in the mid-90's a Windows drone said "Name one thing you can do on a Mac that I can't do on Windows" -> "Use 12 characters in a filename." -> Silence. Spaces were also possible in those 12 characters)

2
  • 1
    I used to use V6 Unix (c. 1978). Spaces were allowed then. One task I had was to write a program to parse the file system (using direct disk i/o) and look for a file which had spaces and backspaces in its name.
    – wallyk
    Commented Aug 3, 2014 at 15:42
  • do they drop spaces altogether - or do the filenames contain a very few spaces?
    – mikeserv
    Commented Aug 4, 2014 at 5:27
1

So yes, as is stated many times elsewhere, a filename can contain nearly any character. But it needs to be said that a filename is not a file. It does carry some weight as a file attribute in that you typically need a filename to open a file, but a file's name only points to the actual file. It is a link, stored in the directory that has recorded it, alongside the inode number - which is a much closer approximation to an actual file.

So, you know, call it whatever you want. The kernel doesn't care - all file references it will handle will deal with real inode numbers anyway. The filename is a thing for human consumption - if you wanna make it a crazy thing, well, it's your filesystem. Here, I'll do some crazy stuff:

First I'll create 20 files, and name them with nothing but spaces, each filename containing one more space than the last:

until [ $((i=$i+1)) -gt 20 ]
do  v=$v' ' && touch ./"$v"
done

This is kinda funny. Look at my ls:

ls -d ./*
./      ./          ./              ./                  ./                 
./      ./          ./              ./                  ./                  
./      ./          ./              ./                  ./                   
./      ./          ./              ./                  ./     

Now I'm going to mirror this directory:

set -- * ; mkdir ../mirror
ls -i1qdU -- "$@" |
sh -c 'while read inum na
    do  ln -T "$1" ../mirror/$inum
    shift ; done' -- "$@"
ls -d ../mirror/*

Here are ../mirror/'s contents:

../mirror/423759  ../mirror/423764  ../mirror/423769  ../mirror/423774
../mirror/423760  ../mirror/423765  ../mirror/423770  ../mirror/423775
../mirror/423761  ../mirror/423766  ../mirror/423771  ../mirror/423776
../mirror/423762  ../mirror/423767  ../mirror/423772  ../mirror/423777
../mirror/423763  ../mirror/423768  ../mirror/423773  ../mirror/423778

Ok, but maybe you're asking - but what good is that? How can you tell which is which? How can you even be sure you linked the right inode number to the right filename?

Well...

echo "heyhey" >>./'    ' 
tgt=$(ls -id ./'    ')
cat ../mirror/${tgt%% .*} \
    $(ls -1td ../mirror/* | head -n1) 

OUTPUT

heyhey
heyhey

See, both the inode number contained in ../mirror/"${tgt%% .*}" and that referenced by ./' ' refer to the same file. They describe the same file. They name it, but nothing more. There is no mystery, really, just some inconvenience you might make for yourself, but which will ultimately have little to no effect on the operation of your unix filesystem in the end.

0

Reading the answers in this question, with a note that this question is ask on a forum about Unix & Linux, it seems to me that the advice against filename with spaces doesn't really come from the problem with Unix & Linux, but comes from other backgrounds.

Take a look at these duplicated questions but in other sites to see how others in other backgrounds perceive this:

Here are the reasons to avoid spaces in filename I find helpful for me:

  • When you put filenames in variables, you need to quote it properly. Instead of foo $filename, you have to write foo "$filename". In some cases, you need to even put it the raw string (e.g. String.raw in JavaScript)
  • If after the space there is a number, and the file is serve online, then the encoding will make the name confusing: image 1.jpg -> image%201.jpg
  • If the backend programmer doesn't handle HTTP code properly (probably because of the first bullet), then when a user download Product list.pdf, they will get a file whose name is only Product.
  • In Python, filename is used as the identifier for imported modules (i.e. foo.py will be imported as foo). Since identifiers can't have spaces, the import statement won't recognize modules with spaces
  • Docker, Git doesn't support spaces in the name
1
  • well that first bullet point is rather a big issue on Unix-like systems, at least based on reading questions on this site...
    – ilkkachu
    Commented Aug 13 at 16:59

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .