5

When I list files that have spaces in their names, most of the time I see them surrounded by apostrophes :

'famille, vacances, loisirs'

I had to edit a file whose name had to be : Chapitre 2 : L'accès au système.md, with an apostrophe inside of it.


I tried :

gvim 'Chapitre 2 : L''accès au système.md'

doubling the apostrophe in the middle. But it created the file 'Chapitre 2 : Laccès au système.md' instead, with no apostrophe at all.


I tried :

gvim "Chapitre 2 : L'accès au système.md"

and it created a file named : "Chapitre 2 : L'accès au système.md"


I have two questions :

  1. Is (for the system) the file name : "Chapitre 2 : L'accès au système.md" the same than a file named 'Chapitre 2 : L'accès au système.md' if I had succeded in doing so ?

  2. how should I write the file name in my gvim command to get the exact file name 'Chapitre 2 : L'accès au système.md' I would like to read in the outpout of a ls command ?

1

3 Answers 3

7

You're using some system where ls outputs filenames with the shell's quoting rules, to make the output unambiguous. Possibly e.g. GNU ls with QUOTING_STYLE set to shell, or ls from coreutils >= 8.25 where that is the default. The quoting rules of the shell are also important when entering the filenames on the command line.

gvim 'Chapitre 2 : L''accès au système.md' created the file 'Chapitre 2 : Laccès au système.md' instead, with no apostrophe at all.

You gave the shell two back-to-back single-quoted strings, which just get concatenated. In SQL, you can get a literal single quote that way, but in the most common shells you can't(†). The outer single quotes you show shouldn't be part of the file name, they're just what ls shows to make the output unambiguous. The actual filename is Chapitre 2 : Laccès au système.md.

(† POSIX-style shells (like Bash, ksh, and zsh with default settings), (t)csh, and fish take that as concatenation, which is how it works in e.g. Python too. Some other shells (rc/es/akanga) do what SQL does, though, and zsh has the rcquotes option for that.)

gvim "Chapitre 2 : L'accès au système.md" created a file named : "Chapitre 2 : L'accès au système.md"

It most likely created a file called Chapitre 2 : L'accès au système.md. The double quotes aren't part of the name, they're just printed by ls to make the output unambiguous. It used double quotes instead of single quotes here, since the name had a single quote but nothing that would be special in double quotes, so that format was the cleanest. Though


  1. Is (for the system) the file name : "Chapitre 2 : L'accès au système.md" the same than a file named 'Chapitre 2 : L'accès au système.md' if I had succeded in doing so?

If those were the full filenames -- and they're valid as filenames! -- then no, they're not equivalent, since the other contains two double quotes and one single quote, and the other contains three single quotes.

If you mean if they're the same when interpreted using the quoting rules of the shell, then no, again. "Chapitre 2 : L'accès au système.md" represents the string Chapitre 2 : L'accès au système.md, as a single shell word (since the quotes keep it together).

On the other hand, 'Chapitre 2 : L'accès au système.md' represents the strings Chapitre 2 : Laccès, au, système.md (three distinct shell words since there are unquoted spaces) and an open quote with no closing partner. If you entered that on the shell command line, it would wait for input from another line in hope of getting the closing quote. If you entered those as arguments to a command on the shell command line without the final stray quote, that command would probably try to access those three distinct files.

  1. how should I write the file name in my gvim command to get the exact file name 'Chapitre 2 : L'accès au système.md' I would like to read in the outpout of a ls command ?

You can't get ls to output 'Chapitre 2 : L'accès au système.md' in the mode where it outputs shell-style quoted strings, since that's not a valid shell-style quoted string: it has an unclosed quote in the end.


Now, if we go back to what you said first:

I had to edit a file whose name had to be : Chapitre 2 : L'accès au système.md, with an apostrophe inside of it.

There's a few ways to represent that in the shell. One of them is using double quotes, which ls also did for you: "Chapitre 2 : L'accès au système.md". This works because none of the characters inside are special in double quotes (it only has spaces and the single quote to protect), but wouldn't work if the filename contained e.g. a dollar sign. If it did have dollar signs, you could escape them with a backslash: \$.

Another way is to use single quotes for everything but the single quote itself, and to put an escaped single quote where we want one: 'Chapitre 2 : L'\''accès au système.md'. That has three parts: 'Chapitre 2 : L', \', and 'accès au système.md', the quotes and backslash get removed, and the result is concatenated to the single word Chapitre 2 : L'accès au système.md.

6
  • I recommend find -maxdepth 1 to view the filenames in this case. ls, on the other hand, loves to add bells and whistles to the output.
    – Quasímodo
    Commented Jul 25, 2020 at 12:38
  • @Quasímodo, it depends... getting an unambiguous output can be useful too. If you encounter a filename with a trailing space, the quotes surrounding it start to look very useful. In any case, ls --quoting-style=literal or export QUOTING_STYLE=literal works in GNU ls to get the old behaviour without quoting the output. It's not entirely literal, though, GNU ls replaces e.g. newlines with ? when printing to a terminal.
    – ilkkachu
    Commented Jul 25, 2020 at 13:12
  • (1) Obviously (?), ls --quoting-style=shell would give the output that the OP is seeing, and ls could be aliased to that. If so, and the shell style isn’t also set as the hard-coded default in ls (ugh) or set by the environment variable, the user can probably get literal filename output by saying \ls to suppress the alias.  … (Cont’d) Commented Jul 26, 2020 at 3:11
  • (Cont’d) …  (2) You can use ls -b, --quoting-style=c or --quoting-style=escape to see control characters in C style (e.g., \r or \016), or --show-control-chars to get them literally (i.e., raw). (--quoting-style=c will also enclose the entire name in " quotes, and escape any quotes in the name.) Commented Jul 26, 2020 at 3:11
  • @G-ManSays'ReinstateMonica', it's the hardcoded default, see gnu.org/software/coreutils/quotes.html .
    – ilkkachu
    Commented Jul 26, 2020 at 7:42
5

For both questions, escape the special characters with \, so they are not interpreted (I assume it is bash). Following your example:

ls Chapitre\ 2\ :\ L\'accès\ au\ système.md
or
gvim Chapitre\ 2\ :\ L\'accès\ au\ système.md.

See the Bash Reference Manual for more info.

3

Names with spaces and special chars is always a source of problems. Quoting is always tricky...

gvim "Chapitre 2 : L'accès au système.md" 

is working as you wanted. ls is showing extra quotes (") to clearer delimit the filename, but the quotes are not in the name.

If you do ls | more you will see the names without the protections.



If you really need more complex names (bad idea) you can concatenate quoted block and protected elements(see @ferranm).

Example - a file named a filename with quotes", apostrophes 'and bars (\) may be created as the sum of 3 blocks "a filename with quotes" + '", ' + "apostrophes 'and bars (\)"

touch "a filename with quotes"'", '"apostrophes 'and bars (\)"

You must log in to answer this question.

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