Search code examples
bashifs

In BASH, test if file exists does not work when filename in variable has single quotes


[Update]

1) I have a file (a.cfg) that contains lines like this:

FILE;'/tmp/testfile';;;+;'Add this line';$;Y

2) In my script, I read this file line by line :

while read line
do
...
done < a.cfg

3) When a line has been read, and it is not empty, I split up the line using IFS :

IFS=';' read a b c d e f g h <<< $line

4) To be sure, I echo the contents of $b. It returns :

'/tmp/testfile'

including the single quotes.

5) Next, I want to see if the location stored in $b exists :

if ! [ -e "$b" ]
then
  echo "not found"
else
  echo "found"
fi

This returns not found....

6) When I do an ls -l '/tmp/testfile' from the prompt (again, including single quotes), I get :

-rw-r--r-- 1 root root 0 Jul 10 22:22 /tmp/testfile

(Did I mention I'm doing all of this as root ?)

7) I tried the above if statement in several ways, but the result remains the same :

if [ ! -e $b ]
if ! [ -e "$b" ]
if [[ ! -e $b ]]
if ! [[ -e $b ]]

So, please tell me where I'm thinking not right....

[End update]

I'm trying to test if a file exists by passing the contents of a variable to the test -e of bash. The variable looks like this :

FILE1='/etc/wherever/whatever'

When i do :

[[ -e "$FILE1" ]]

$? equals to 1, and it says it can't find the file (above path is an example....)

Tried several options: double quotes around the filepath instead of single quotes (variable is obtained from a line in a file)

Found out it only works if I put the filepath in the file I read without any quotes. But that would be a problem when using filenames withe spaces in it.

So, to clarify: 1) file contains lines that are read one by one 2) columns in line are split using IFS into separate variables 3) one variable is a filename, that is enclosed in single quotes 4) a [[ -e $variable ]] can't find the file.

What would be the correct syntax, please ?


Solution

  • This happens because you have literal quotes in your string, and they are not being interpreted as shell script code.

    Consider this PHP code:

    $x="1+1";
    echo 1+1;   # Writes 2
    echo $x;    # Writes 1+1, not 2
    

    It works the same way in Bash:

    var="'myfile'"
    [[ -e 'myfile' ]]  # Checks for a file called  myfile 
    [[ -e $var ]]      # Checks for a filename with apostrophes in it, not  myfile
    

    You have to extract the exact filename you want. Since your filename doesn't contain apostrophes, you should strip them:

    var="'myfile'"
    var=${var//\'/}  # Replace all apostrophes with nothing
    if [[ -e $var ]]
    then
      echo "Exists"
    fi