Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

BASH cannot find hidden file that exists using ~/ in path

I have a BASH script that is looking for a hidden file in my home directory. When I specify the absolute path /home/user/.foo in trying to find the file then the script will find it but if I use ~/.foo then the script cannot find the file. Can someone explain why this is happening and what other way I can find the file. I want to be able to find the file on different user's home directory and not just my own.

Sorry for not providing the snippet of code but here it is

file="~/.foo"

[ -f $file ] && echo "foo exists!"

this however works

file="home/user/.foo"

[ -f $file ] && echo "foo exists!"

like image 222
user2989027 Avatar asked Dec 24 '22 15:12

user2989027


2 Answers

This is because the shell only performs tilde expansion when the tilde is the first unquoted character in a word. In

file="~/.foo"

the tilde is quoted with double quotes, so is left unexpanded. The best practice is to always use $HOME when the tilde is supposed to expand to your home directory (and not some other user's as in ~user.

The straight dope from POSIX:

2.6.1 Tilde Expansion

A "tilde-prefix" consists of an unquoted <tilde> character at the beginning of a word, followed by all of the characters preceding the first unquoted <slash> in the word, or all the characters in the word if there is no <slash>. In an assignment (see XBD Variable Assignment), multiple tilde-prefixes can be used: at the beginning of the word (that is, following the <equals-sign> of the assignment), following any unquoted <colon>, or both. A tilde-prefix in an assignment is terminated by the first unquoted <colon> or <slash>. If none of the characters in the tilde-prefix are quoted, the characters in the tilde-prefix following the <tilde> are treated as a possible login name from the user database. A portable login name cannot contain characters outside the set given in the description of the LOGNAME environment variable in XBD Other Environment Variables. If the login name is null (that is, the tilde-prefix contains only the tilde), the tilde-prefix is replaced by the value of the variable HOME. If HOME is unset, the results are unspecified. Otherwise, the tilde-prefix shall be replaced by a pathname of the initial working directory associated with the login name obtained using the getpwnam() function as defined in the System Interfaces volume of POSIX.1-2008. If the system does not recognize the login name, the results are undefined.

The pathname resulting from tilde expansion shall be treated as if quoted to prevent it being altered by field splitting and pathname expansion.

like image 192
Jens Avatar answered Jan 07 '23 07:01

Jens


Always provide the code which does not work. From your description it cannot be reproduced:

$ ls ~/.foo
/home/user/.foo

As suggested by anishsane there may be quotes.

$ ls "~/.foo"
ls: cannot access ~/.foo: No such file or directory

But how to handle white space? Put the ~ outside the quotes:

$ ls ~/".f o o"
/home/user/.f o o

But also but the / outside the quotes, else ~ is not expanded

$ ls ~"/.f o o"
ls: cannot access ~/.f o o: No such file or directory
like image 20
Gunstick Avatar answered Jan 07 '23 07:01

Gunstick