25

This doesn't work:

$ ls "~/.wine/drive_c/tools/Family Tree v2.0"
ls: cannot access '~/.wine/drive_c/tools/Family Tree v2.0': No such file or directory

But this does:

$ ls "/home/daniel/.wine/drive_c/tools/Family Tree v2.0"
Dossiers                           Dossiers_orig   Infos.opt      Racines.exe  'Register OCX.bat'   racines.CNT
Dossiers-2019.11.03-11.46.tar.gz   Html            REGSVR32.exe   Racines.hlp   Uninst.isu          readme.txt

Given that ~ is supposed to be the same as /home/daniel, what's going on here?

4
  • 22
    @Pilot6 No, in both examples shown, the path is quoted. The problem is that quoting suppresses tilde expansion. (I've posted an answer.) Dec 1, 2019 at 16:10
  • 2
    The expansion of ~ to your home directory is a function of the shell you're using (bash, csh, etc), which expands ~ to $HOME et al before actually invoking the command. But quoting (double and single) is used to tell the shell to act differently, e.g. to include any spaces (the most common use) or other unusual characters that might be interpreted by the shell (like !! for history access, or $ for variable access). So ls $A show the contents of the directory name stored in environment variable A, and ls '$A' shows the contents of the directory literally called $A
    – simpleuser
    Dec 2, 2019 at 5:35
  • Difference between $HOME and ~
    – phuclv
    Dec 2, 2019 at 10:07
  • 2
    Possible duplicate of Why can't I cd to a quoted tilde ('~')?
    – phuclv
    Dec 2, 2019 at 10:08

1 Answer 1

56

Quoting, even with double quotes, suppresses tilde expansion.

~ can be used as a path to your home directory in contexts where tilde expansion is performed. ~ is not like . or ... There aren't actually any entries in your filesystem called ~ that serve as alternate names for your home directory.

When ~ appears by itself or as the first component of a path, your shell expands it into an absolute path to your home directory. But this does not happen when ~ is quoted. Double quotes provide a weaker form of quoting than single quotes, which is important to some other kinds of expansion, such as parameter expansion (which expands $HOME). But even double quotes suppress tilde expansion.

Thus ~ was not expanded in this command, where it is quoted:

ls "~/.wine/drive_c/tools/Family Tree v2.0"

Fortunately, it is permitted to write an argument some of whose parts are quoted and some of whose parts are not. So you can put ~/ before the quotes, and still quote the rest:

ls ~/".wine/drive_c/tools/Family Tree v2.0"

Or, since parameter expansion is performed even in double quotes--but not in single quotes--you can use:

ls "$HOME/.wine/drive_c/tools/Family Tree v2.0"

(Technically that is different, in that even when the HOME environment variable is unset, some shells still try to figure out what your home directory is and expand ~ to it--and bash is one such shell. But it's both rare and inadvisable to have HOME unset.)


Further reading:

2
  • 2
    "Fortunately, it is permitted to write an argument some of whose parts are quoted and some of whose parts are not." It is even permitted to mix it arbitrarily - this is called string concatenation, e.g. ~/'.wine'"/driv"'e_c/'tools'Family Tree v2.0'. Just ~/ needs to be unquoted. Dec 2, 2019 at 14:30
  • 3
    @rexkogitans: Terminology: It would be "string concatenation" in a language like C where string text must be quoted. But this is shell; formally it's just a consequence of the quote-removal rules. There never were separate strings to get concatenated. Quote removal of paired '' and "" quotes simply happens after word-splitting and all(?) expansions, including tilde. Dec 3, 2019 at 16:04

You must log in to answer this question.

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