When I input a relative directory path name using the 'read' command in Bash, it is not recognized as a valid directory by the -d test:
Relative directory path ~/tmp fails the if/-d test:
corba@samwise:~$ read CMDLINE_FILENAME
~/tmp
corba@samwise:~$ echo "$CMDLINE_FILENAME"
~/tmp
corba@samwise:~$ if [ -d $CMDLINE_FILENAME ]; then echo "Valid directory!"; fi
corba@samwise:~$
Relative directory path ../tmp fails the if/-d test:
corba@samwise:bin$ read CMDLINE_FILENAME
../tmp
corba@samwise:bin$ echo "$CMDLINE_FILENAME"
../tmp
corba@samwise:bin$ if [ -d $CMDLINE_FILENAME ]; then echo "Valid directory!"; fi
corba@samwise:~$
But an absolute directory path succeeds:
corba@samwise:~$ read CMDLINE_FILENAME
/home/corba/tmp
corba@samwise:~$ echo "$CMDLINE_FILENAME"
/home/corba/tmp
corba@samwise:~$ if [ -d $CMDLINE_FILENAME ]; then echo "Valid directory!"; fi
Valid directory!
corba@samwise:~$
I expected if [ -d ~/tmp ]
and if [ -d ../tmp ]
to be recognized as valid directory names. They were not.
I tried the solution that was offered in How to manually expand a special variable (ex: ~ tilde) in bash, but it only works for tilde and not for other relative paths like ../
, ../../
, or ./
I tried the variations of quoting/double-quoting and single/double square brackets in the if
statement and get the same error in all cases. And these errors occur on MSYS2 (Git Bash) and Ubuntu 22.
CodePudding user response:
~/tmp
actually is an absolute path from the bash point of view. However this relies on bash to substitute the ~
to the user accounts home folder path, so to something like /home/users/someone/tmp
which clearly is an absolute path. That is a buildin feature of the bash shell usually called "path expansion". A relative path would be something like ./tmp
or just tmp
, so something that has to be interpreted relative to the current working directory of the process.
That substitution does not get applied here apparently. You can use a slightly altered command to achieve what you are looking for by explicitly forcing such expansion in a sub shell command:
if [ -d `eval echo $CMDLINE_FILENAME` ]; then echo "Valid directory!"; fi
That one works for absolute and relative paths, but also for entries that rely on the bash path expansion:
bash:~$ read CMDLINE_FILENAME
~/tmp
bash:~$ echo "$CMDLINE_FILENAME"
~/tmp
bash:~$ if [ -d `eval echo $CMDLINE_FILENAME`]; then echo "Valid directory!"; fi
Valid directory!
This does carry the risk of miss usage, though: the eval
directive is a pretty mighty tool ...