GNU Coreutils - Quoting File names

Overview

Starting with GNU coreutils version 8.25 (released Jan. 2016), ls's default output quotes filenames with special characters:

$ ls
'filename with a $ dollar sign'
"filename with a ' single-quote"
'filename '\'' with many " quotes'
'filename with spaces'
 filename_with_underscores

Rationale

The reasons to change the default output are (source) :

  • Unambiguous output

    The new default output format results in unambiguous file names, making it easier for users to deal with filenames containing special characters:

    $ ls --quoting-style=literal      ## the old default quoting style
    a!b  a?b  a?b  axb  c  d  e
    
    $ rm a?b c d e
    rm: cannot remove 'd': No such file or directory
    rm: cannot remove 'e': No such file or directory

    With the new default quoting output, filenames with spaces and other characters are clearly visible:

    $ ls
    'a!b'  'a?b'  'a'$'\n''b'   axb   c  'd  e'
  • Easier and safer cutting and pasting of filenames from/to the terminal

    Without quotes, filenames containing special shell characters are problmatic to copy and paste easily. In the following example, each of the files has characters that if not quoted, would cause unexpected actions when copy and pasted on the terminal:

    $ ls --quoting-style=literal    ## the old default quoting style
    a*
    a!b
    a'b
    a?b
    a long file name
    a$USER

    With quotes, copying and pasting any of these filenames on the terminal is safe:

    $ ls
    'a*'
    'a!b'
    "a'b"
    'a'$'\t''b'
    'a long file name'
    'a$USER'

    (bug24926#20)

  • Quotes only appear when outputting to terminals so they don't break scripts.

  • Users can get back to the old format by adding -N to their ls alias.

Frequently Asked Questions and Comments

How to restore the old behaviour?
How to print filenames without quotes?

ls -N prints filenames without quotes (same as the default behaviour prior to version 8.25).
Equivalent options are ls --literal and ls --quoting-style=literal.

How to change quoting permanently?

The simplest method is adding a shell alias:
alias ls="ls -N"
To your shell's configuration file (e.g. $HOME/.profile, or $HOME/.bash_profile for bash, $HOME/.zprofile for zsh).

Another option is setting the QUOTING_STYLE environment variable to literal in your shell configuration file, e.g.:
export QUOTING_STYLE=literal

(bug22696#68)

“The quotes break my scripts! This is a serious regression.”

No, the new quotes feature does not break scripts.
Quotes around filenames, just like color output, are only printed when the output device (STDOUT) is a terminal (tty). Redirecting the output to a file or piping it to another program prints the filenames without quotes:

$ ls -1
'a long file name'
a_long_file_name
'hello world'
hello_world

$ ls -1 | cat
a long file name
a_long_file_name
hello world
hello_world

(bug25078#17, bug25388#8)

“Having ls add quotes when printing to the terminal, but no quotes when piping to another program is a bad practice.”

This has been the standard behaviour since the 1980s: ls shows multicolumn output when the output is a tty, and single-column output when piped into a pager. Similarly for color output.

Additionally, this behaviour is codified by the POSIX standard.

(bug25388#14, bug25388#26)

“Don't you think I can see the spaces in my filenames?”

Not in general, no. For example:

$ ls --quoting-style=literal
a  b  c

$ ls
'a  b'  c

(bug24926#8)

ls -1 aligns output differently than ls.

This is intentional, but may change in the future.
When ls -1 is used interactively it can be handy to triple click to select the whole line, in which case selecting just the file name without leading space would be preferred.

One can achieve the desired (aligned) output with ls -w1 or ls -x -w1 | less:

$ ls
'a long file name'
 a_long_file_name
'hello world'
 hello_world

$ ls -1
'a long file name'
a_long_file_name
'hello world'
hello_world

$ ls -w1
'a long file name'
 a_long_file_name
'hello world'
 hello_world

(bug25708#8)

What about readlink, basename, dirname, mktemp... Why they don't have a terminal mode too?

If a command is commonly used at the top level, it probably should do something like 'ls' does, yes. The above commands aren't often used for that, though, so it's not high priority to change them.

(bug22696#22)

New users should learn (the hard way) that non-ascii filenames are bad, and shouldn't be used.
Users who have filenames with special characters should use GUI programs (e.g. Konqueror, Gnome Shell, PCManFM) to point-and-click at files instead of using the command-line.
We can't control what stupid file names come from other users or downloaded from the internet, and we shouldn't cater to them.

The coreutils maintainers think we should encourage new users and make them feel welcome.

This is partly why the new behavior is more important now than it used to be. Too many naive users are running 'ls' in directories from untrustworthy sources.

(bug22696#22)

“The ‘copy & paste’ reason is only relevant on a graphic terminal.”

Not so; it's relevant even on (for example) a shell session in a non-graphical Emacs running on a traditional terminal or a Linux console.

These days, how many users are NOT using a graphical terminal? Again, it only affects output to a terminal, and it is very easy to adjust your login setups to change the defaults to something you like, so that _your_ terminal behaves the way you want.

(msg #4)

“This change was made by a single individual unilaterally and we find it unacceptable!”
“You added a new kind of quoting style and even enabled it by default within the same patch-set. No user on earth was able to test the new quoting style nor anybody had asked you to make it the default. I don't see that it was ‘carefully considered’.”

At the time it was added there was no stated opposition to the idea by reviewers. There seemed little point to delaying the change to the default behavior, considering that the change improves security.

(msg #1, msg #2, msg #3, bug22696#16, bug23896#11)

“Files with single quotes are printed in a ridiculous way!”

This issue was quickly fixed in version 8.26:

$ touch "Don't README.txt"

$ ls-8.25
'Don'\''t README.txt'   ## version 8.25

$ ls
"Don't README.txt"      ## version 8.26 and later

(bug22696#19)

“Quoting files causes ugly and misaligned columns.”

This issue was quickly fixed in version 8.26:

$ ls-8.25
'a long file name'  'hello world'
a_long_file_name    hello_world

$ ls
'a long file name'  'hello world'
 a_long_file_name    hello_world

And similarly with ls -l:

$ ls-8.25 -lgo
total 0
-rw-r--r-- 1 0 Nov  9 01:12 'a long file name'
-rw-r--r-- 1 0 Nov  9 02:32 a_long_file_name
-rw-r--r-- 1 0 Nov  9 01:11 'hello world'
-rw-r--r-- 1 0 Nov  9 02:32 hello_world

$ ls -lgo
total 0
-rw-r--r-- 1 0 Nov  9 01:12 'a long file name'
-rw-r--r-- 1 0 Nov  9 02:32  a_long_file_name
-rw-r--r-- 1 0 Nov  9 01:11 'hello world'
-rw-r--r-- 1 0 Nov  9 02:32  hello_world

(bug24926#5)

Rejected Ideas

  • Create a build-time (./configure) option to set the default quoting style.

    Such behaviour goes against the GNU coding style, which says “No ‘--enable’ option should ever substitute one useful behavior for another useful behavior.”

    (bug22696#34, bug22696#37)

  • Revert the change, set default quoting back to “literal.”

    GNU Coreutils maintainers are of the opinion that this change is beneficial to most users, and there is no plan to revert it.
    It is very easily to change the default quoting for your own account (using alias), or globally (using QUOTING_STYLE).

    (bug22696#40)

More information and bug reports

  • See the coreutils web page for details about Getting Help, searching the archives for past questions and discussions.
  • Send questions or suggestions to <coreutils@gnu.org>. PLEASE ensure these were not already addressed above.
  • If you suspect a bug, send bug reports to <bug-coreutils@gnu.org>. please provide version details, environment details, and exact commands to reproduce the bug.