Shell脚本检查文件是否存在并具有读取权限

3
在我的shell脚本中,我正在尝试检查特定文件是否存在以及是否具有读取权限。
我的文件路径中包含空格。
我将文件路径加上引号:
file='/my/path/with\ some\ \spaces/file.txt'

这是用于检查文件是否存在的函数:

#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
}

在这里我使用双引号以确保将文件作为一个参数传递:

checkIfFileExists "'$file'";

我从bash中收到一个错误信息:

[: too many arguments

我认为它不能将其作为一个参数。

但是在我的自定义错误中,我获取了整个路径,并且它说不存在。

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

虽然文件确实存在,但当我尝试使用“cat $file”读取它时,出现了权限错误。我做错了什么?

你也可以使用复合命令 [ ! -r "$1" ] && some command || other command 代替完整的 if [..]; then some command; else other command; fi -- 但无论哪种情况下都要引用你的变量。 - David C. Rankin
2个回答

2

当需要使用变量插值时,正确的引用方式是使用双引号:

if [ -e "$1" ]; then

在脚本中需要使用相似的引号,而调用者需要引用或转义字符串,但不能同时进行。当你赋值时,请使用以下之一:

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"

然后使用双引号将值括起来,以单个参数的形式传递:

checkIfFileExists "$file"

再次提醒,在需要使用变量值进行插值的地方,请使用双引号。

为了快速说明这些引号的作用,请尝试以下操作:

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

此外,还可以参考何时在shell变量周围加上引号?

明白了,这很有道理。看起来现在它把它作为一个整体了。虽然文件存在,但-e为什么返回false呢?我知道它存在并且权限不足。如果我试图打开它,它会告诉我由于权限而无法打开。 - Asaf Nevo
我认为这是因为我路径中有转义\的原因,可能是这个原因吗? - Asaf Nevo
啊,是的;要么引用或者转义空格,但不要两者都做。我会进一步更新答案。 - tripleee

-1
if [[ -e $1 ]];then
 echo it exists
else
 echo it doesnt
fi

if [[ -r $1 ]];then
  echo readable
else
  echo not readable
fi

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接