3

In my shell script i'm trying to check if a specific file is exists and if it has reading permissions.

My file's path has spaces in it.

I quoted the file path:

file='/my/path/with\ some\ \spaces/file.txt'

This is the function to check if the file exists:

#Check if file exists and is readable
checkIfFileExists() {
    #Check if file exists
    if ! [ -e $1 ]; then
        error "$1 does not exists";
    fi

    #Check if file permissions allow reading
    if ! [ -r $1 ]; then
        error "$1 does not allow reading, please set the file permissions";
    fi
}

Here I double quote to make sure it gets the file as a one argument:

checkIfFileExists "'$file'";

And I receive an error from the bash saying:

[: too many arguments

Which make me thinks it doesn't get it as a one argument.

But in my custom error, I do get the whole path, and it says it doesn't exists.

Error: '/my/path/with\ some\ \spaces/file.txt' does not exists

Although it does exists, and when I tried to read it with "cat $file" I get a permission error..

what am I'm doing wrong?

Asaf Nevo
  • 11,338
  • 23
  • 79
  • 154
  • You can also use compound commands `[ ! -r "$1" ] && some command || other command` instead of full `if [..]; then some command; else other command; fi` -- but always quote your variables in either case. – David C. Rankin Nov 23 '15 at 09:18

2 Answers2

2

The proper way to quote when you require variable interpolation is with double quotes:

if [ -e "$1" ]; then

You need similar quoting throughout the script, and the caller needs to quote or escape the string -- but not both. When you assign it, use one of these:

file='/my/path/with some spaces/file.txt'
# or
file=/my/path/with\ some\ spaces/file.txt
# or
file="/my/path/with some spaces/file.txt"

then use double quotes around the value to pass it in as a single argument:

checkIfFileExists "$file"

Again, where you need the variable's value to be interpolated, use double quotes.

For a quick illustration of what these quotes do, try this:

vnix$ printf '<<%s>>\n' "foo bar" "'baz quux'" '"ick poo"' \"ick poo\" ick\ poo
<<foo bar>>
<<'baz quux'>>
<<"ick poo">>
<<"ick>>
<<poo">>
<<ick poo>>

Furthermore, see also When to wrap quotes around a shell variable?

Community
  • 1
  • 1
tripleee
  • 175,061
  • 34
  • 275
  • 318
  • Got it, and it make sense.. It does look like now it takes it as a whole.. is there a reason why -e return false although the file exists? I know it exists and have bad permissions.. If i'm trying to open it - it tells me it can because of permissions – Asaf Nevo Nov 23 '15 at 11:56
  • I think it is because of the escaping \ I have in my path.. could it be? – Asaf Nevo Nov 23 '15 at 11:59
  • Ah yes; either quote *or* escape the spaces, but not both. I'll update the answer some more. – tripleee Nov 23 '15 at 12:05
-1
if [[ -e $1 ]];then
 echo it exists
else
 echo it doesnt
fi

if [[ -r $1 ]];then
  echo readable
else
  echo not readable
fi
Vishnu
  • 220
  • 1
  • 8