您好,我正在尝试执行 if 操作,它获取目录路径作为参数,并检查 file.txt 是否在目录中。如果是,则返回 1,否则返回 0。
if [ -e $1/file.txt ]; then
exit 1
else exit 0
fi
我也尝试过 ls 方法
ls $1/file.txt && exit 1 || exit 0
还有其他方法吗?或者我错过了什么?
答案1
file.txt
要检查作为第一个参数传递给脚本或函数的目录中是否存在文件,请使用
[ -e "$1/file.txt" ]
如果文件存在则成功,如果文件不存在则失败。失败包括文件存在但无法访问的情况,例如因为您没有遍历目录的权限。
请注意,在 shell 脚本中,当涉及进程退出状态时,0 表示成功,1(或更多,最多 125)表示失败。看我可以在 bash 函数/脚本中使用哪些返回/退出值?和进程终止时的默认退出代码?更多细节。因此,如果您想检查文件是否存在,则脚本或函数必须在文件存在时返回 0,否则返回 1。您的代码片段执行相反的操作:它检查文件是否不存在。
if [ -e "$1/file.txt" ]; then
exit 0
else
exit 1
fi
只是一种更复杂的写法
[ -e "$1/file.txt" ]
exit
(exit
没有状态参数时使用先前执行的命令的状态)。如果这是在脚本的末尾,那么这exit
是多余的。
!
如果您确实想检查该文件是否不存在,那么您可以使用shell 运算符反转命令:
! [ -e "$1/file.txt" ]
或!
test
/[
运算符:
[ ! -e "$1/file.txt" ]
答案2
[ -e "$1/file.txt" ]
在支持它的shell/[
实现中,如果可以对stat()
路径为$1/file.txt
.
它相当于:
if ls -Ld -- "$1/file.txt" > /dev/null 2>&1
相当于:
if ls -d -- "$1/file.txt" > /dev/null 2>&1
即是否lstat()
可以对文件执行 a 操作,它将是:
if [ -e "$1/file.txt" ] || [ -L "$1/file.txt" ]
覆盖“损坏的”符号链接情况(-e
在符号链接解析后测试是否存在时将返回 false)。
现在,stat()
,lstat()
失败并不一定意味着该文件不存在,stat()
/lstat()
可能会因 ENOENT(无条目)ENOTDIR(路径组件不是目录)以外的其他错误条件而失败。例如,您可能没有对任何目录组件的搜索访问权限。
通过该ls
方法,您可以删除2>&1
forls
来告诉您错误。有了[
,你不会知道,除非你使用zsh
你可以使用的地方$ERRNO
。
如果你没有搜索访问该目录,您可能仍然拥有读访问权限,因此您仍然可以读取目录内容以查看是否存在同名的文件。
对于zsh
,可以通过 匿名函数 来完成()(($#)) $1/file.txt(N)
,如果它接收到至少一个参数 ( ),我们将与该glob()(($#))
匹配的文件列表传递给该参数,该匿名函数将返回 true,即为该 glob打开。$1/file.txt(N)
(N)
NULLGLOB
一个单独的问题是其中is 的$1/file.txt
情况,在这种情况下,在某些系统上 that 变为which 与 不同。$1
/
//file.txt
/file.txt
因此zsh
,使用 来检查目录file.txt
中是否存在条目$1
:
exists() {
local file="${1%/}/file.txt"
zmodload zsh/system
local ERRNO=0
[ -e "$file" ] || [ -L "$file" ] && return 0
case $errnos[ERRNO] in
(ENOENT|ENOTDIR) return 1;; # does not exist for sure
(*) ()(($#)) $file && return 0;;
esac
return 2 # meaning: don't know
}
对于其他 shell,您可以尝试:
enoent_error=$(
LC_ALL=C ls -d /surely-does-not-exist 2>&1)
)
enoent_error=${enoent_error##*:}
enotdir_error=$(
LC_ALL=C ls -d /bin/sh/foo)
)
enotdir_error=${enotdir_error##*:}
exists() (
file=${1%/}/file.txt
if error=$(LC_ALL=C ls -d -- "$file" 2>&1 > /dev/null); then
return 0 # exists for sure
else
case $error in
(*:"$enoent_error"|*:"$enotdir_error")
return 1;; # does not exist for sure
esac
fi
return 2 # don't know
}
假设ls
C 语言环境中的错误消息遵循以下*: fixed error message
模式,fixed error message
其中每个错误条件都不同,但对于给定错误始终相同,并且不包含:
(仅在我的系统上ETOOMANYREFS
(参考太多:无法拼接) 在相应的标准 libc 错误消息中有一条:
,但这不是lstat()
, 无论如何返回的 errno无法拼接在其他错误消息中找不到)。
又名[
最初test
不支持-e
。首先ksh
引入-a
(然后兼作一元和二元运算符),对于无障碍我相信(这在某种程度上更正确),后来被重命名为-e
(尽管大多数实现仍然支持-a
),这就是-e
POSIX 为标准test
/[
实用程序指定的。/bin/sh
在 Solaris 10 及更早版本上仍然是非 POSIX Bourne shell,并且其[
内置仍然不支持[ -e
Nor [ -a
,因此如果您要使用该 shell,则需要求助于ls
或调用/bin/test
(尽管您更愿意使用 POSIX shell)就像/usr/xpg4/bin/sh
那里一样)。