Linux 组合两个否定的文件检查条件(-f和-s)似乎会返回不正确的结果

Linux 组合两个否定的文件检查条件(-f和-s)似乎会返回不正确的结果,linux,bash,Linux,Bash,我想检查一个文件是否是一个文件并且存在,它是否不是空的,因此最后使用了与-f和-s的组合检查。如果文件不存在或为空,我希望提前返回,因此我将否定这两个检查 要测试我的文件名返回空字符串并传递目录路径的场景,我尝试以下操作: if [[ ! -f "/path/to/dir/" ]] && [[ ! -s "/path/to/dir/" ]]; then echo "Does not exists"; else echo "Exists"; fi 存在 以上返回的“存在”,似

我想检查一个文件是否是一个文件并且存在,它是否不是空的,因此最后使用了与
-f
-s
的组合检查。如果文件不存在或为空,我希望提前返回,因此我将否定这两个检查

要测试我的文件名返回空字符串并传递目录路径的场景,我尝试以下操作:

if [[ ! -f "/path/to/dir/" ]] && [[ ! -s "/path/to/dir/" ]]; 
then  echo "Does not exists"; else echo "Exists"; fi
存在

以上返回的“存在”,似乎不正确

-f
单独检查是否正确:

if [[ ! -f "/path/to/dir/" ]]; then  echo "Does not exists"; 
else echo "Exists"; fi
不存在

组合检查(但不否定每个检查)也是正确的:

if [[ -f "/path/to/dir/" ]] && [[ -s "/path/to/dir/" ]]; 
then  echo "Exists"; else echo "Does not exists"; fi
不存在

不确定我是否做错了什么,或者在将否定条件与逻辑and组合时Bash中是否有一些奇怪之处

编辑1: 正如所建议的,如果两个条件都在同一组括号中,则使用符号:

if [[ ! -f "/opt/gmdemea/smartmap_V2/maps/" && ! -s "/opt/gmdemea/smartmap_V2/maps/" ]]; then  echo "Does not exists"; else echo "Exists"; fi
存在

但这并没有改变行为

编辑2: 从手册页上看,在这种情况下,
-s
应该足够了,但当传递现有目录路径时,它返回true(Bash版本:4.1.2(1)-release):

存在


它返回“Exists”,而它不是一个文件,所以应该转到else子句返回“not Exists”

具有
x和y
,然后对它进行唠叨:not(x和y)。这等于
(不是a)或(不是b)
。它不等于
(不是x)和(不是y)

我想检查一个文件是否是一个文件并且存在,它是否不是空的

如果要检查某个文件是否为常规文件且不为空,请执行以下操作:

[[ -f path ]] && [[ -s path ]]
否定式为(每行相等)(注):

您也可以将其写为(每行相等):

所以只要:

if [[ ! -f "/path/to/dir/" || ! -s "/path/to/dir/" ]]; then
     echo "The /path/to/dir is not a regular file or size is nonzero"
else
     echo "The path /path/to/dir is a regular file and it's size is zero"
fi

拥有
x和y
,然后唠叨你会得到:
不是(x和y)
。这等于
(不是a)或(不是b)
。它不等于
(不是x)和(不是y)

我想检查一个文件是否是一个文件并且存在,它是否不是空的

如果要检查某个文件是否为常规文件且不为空,请执行以下操作:

[[ -f path ]] && [[ -s path ]]
否定式为(每行相等)(注):

您也可以将其写为(每行相等):

所以只要:

if [[ ! -f "/path/to/dir/" || ! -s "/path/to/dir/" ]]; then
     echo "The /path/to/dir is not a regular file or size is nonzero"
else
     echo "The path /path/to/dir is a regular file and it's size is zero"
fi

@KamilCuk已经解释了这个逻辑缺陷,但一般来说-始终避免在代码中使用否定词,例如
在这种情况下,因为它们使代码比使用正片更难阅读(并且更难正确)。而不是:

if [[ ! -f "/path/to/dir/" ]] && [[ ! -s "/path/to/dir" ]]
then
    echo "Does not exists"
else
    echo "Exists"
fi
如果您应用布尔代数来计算
s然后您将得到:

if ! ( [[ -f "/path/to/dir/" ]] || [[ -s "/path/to/dir" ]] )
then
    echo "Does not exists"
else
    echo "Exists"
fi
然后,您可以将if/else翻转进来,以摆脱最后的

if [[ -f "/path/to/dir/" ]] || [[ -s "/path/to/dir" ]]
then
    echo "Exists"
else
    echo "Does not exists"
fi
你一眼就能看出这不是你想要的测试。相反,您希望:

if [[ -f "/path/to/dir/" ]] && [[ -s "/path/to/dir" ]]
then
    echo "Exists"
else
    echo "Does not exists"
fi

@KamilCuk已经解释了这个逻辑缺陷,但一般来说-始终避免在代码中使用否定词,例如
在这种情况下,因为它们使代码比使用正片更难阅读(并且更难正确)。而不是:

if [[ ! -f "/path/to/dir/" ]] && [[ ! -s "/path/to/dir" ]]
then
    echo "Does not exists"
else
    echo "Exists"
fi
如果您应用布尔代数来计算
s然后您将得到:

if ! ( [[ -f "/path/to/dir/" ]] || [[ -s "/path/to/dir" ]] )
then
    echo "Does not exists"
else
    echo "Exists"
fi
然后,您可以将if/else翻转进来,以摆脱最后的

if [[ -f "/path/to/dir/" ]] || [[ -s "/path/to/dir" ]]
then
    echo "Exists"
else
    echo "Does not exists"
fi
你一眼就能看出这不是你想要的测试。相反,您希望:

if [[ -f "/path/to/dir/" ]] && [[ -s "/path/to/dir" ]]
then
    echo "Exists"
else
    echo "Does not exists"
fi

请阅读。对于目录,您可能应该使用
if[[!-d”/path/to/dir/“]
。请阅读。对于目录,您可能应该使用
if[[!-d”/path/to/dir/“]
。我正眼望着
/path/to/dir/
末尾的斜线,认为值得一提,但是今天早上很难表达。也许在底部添加一个注释作为旁白,以澄清如果斜杠在那里,它就是一个目录?@Kamil Cuk mybe您使用的是不同的Bash版本(我在4.1.2(1)-发行版上)和-s是不够的。如果我像这样传递现有目录路径:
If[[-s”/opt/gmdemea/smartmap_V2/maps/“];然后回声“存在”;否则echo“不存在”;fi
它返回'Exists',而它不是一个文件,因此应该转到else子句并返回'notexist'。PiotrPanczyk你是对的。我认为它将dir视为大小为零的文件…:/@EdMorton我认为,因为理论上,
[[a].[b]
将运行两个进程,而
[[a].[b]]
将只运行一个进程。请注意,如果
a
在两种情况下均为false,则不会处理
b
。更少的进程通常会导致更快的脚本。而且打字也不太方便。我承认,我对这句话考虑得不够充分(但我认为我无论如何都会支持它,并且仍然会在脚本中使用
&&
|
内部
[[
)@KamilCuk我理解“-s”和你一样,在代码中单独使用,这让我陷入了麻烦。这就是为什么我开始调查这个问题。我斜视着
/path/to/dir/
末尾的斜线,认为它值得评论,但今天早上很难表达。也许在底部添加一个注释作为旁白,以澄清我如果斜杠在那里,它是一个目录?@Kamil Cuk mybe您使用的是不同的Bash版本(我在4.1.2(1)版本上)和-s是不够的。如果我像这样传递现有目录路径:
If[[-s”/opt/gmdemea/smartmap_V2/maps/”];那么echo“存在”;否则echo“不存在”;fi
它返回'Exists',而它不是一个文件,因此应该转到else子句并返回'notexist'。@PiotrPanczyk你是对的。我认为它将dir视为一个大小为零的文件…:/@EdMorton我认为,因为理论上
[[a].[b]
将在
[[a | b]]时运行两个进程
将只运行一个。请注意,如果
a
在这两种情况下都为false,则不会处理
b
。进程越少,脚本的速度通常越快。而且打字也越慢。我承认,我没有充分考虑这一点(但我认为我站得住脚)