に
[ -f "$file" ]
[コマンドがないstat()(ないlstat()に保存されているパス上の)システムコールを$fileして返す真そのシステムコールが成功し、で返されるファイルの種類があればstat()、「ある正規の」。
したがって、[ -f "$file" ]trueが返された場合、ファイルが存在し、それが通常のファイルであるか、最終的に通常のファイルに解決されるシンボリックリンクであるかを確認できます(または、少なくとも当時stat())。
ただし、falseを返す場合(またはif [ ! -f "$file" ]または! [ -f "$file" ]trueを返す場合)には、さまざまな可能性があります。
- ファイルは存在しません
- ファイルは存在しますが、通常のファイルではありません(デバイス、fifo、ディレクトリ、ソケットなどである可能性があります)
- ファイルは存在しますが、親ディレクトリへの検索権限がありません
- ファイルは存在しますが、アクセスするためのパスが長すぎます
- ファイルは通常のファイルへのシンボリックリンクですが、シンボリックリンクの解決に関与する一部のディレクトリに対する検索権限がありません。
- ...
stat()システムコールが失敗する可能性があるその他の理由。
つまり、次のようになります。
if [ -f "$file" ]; then
printf '"%s" is a path to a regular file or symlink to regular file\n' "$file"
elif [ -e "$file" ]; then
printf '"%s" exists but is not a regular file\n' "$file"
elif [ -L "$file" ]; then
printf '"%s" exists, is a symlink but I cannot tell if it eventually resolves to an actual file, regular or not\n' "$file"
else
printf 'I cannot tell if "%s" exists, let alone whether it is a regular file or not\n' "$file"
fi
ファイルが存在しないことを確認するにはstat()、エラーコードENOENT(ENOTDIRがパスコンポーネントの1つがディレクトリではないことを示す別のケースであり、ファイルが存在しないことを示す別のケースが返されることを返すシステムコールが必要です。そのパスに存在します)。残念ながら、この[コマンドではそれがわかりません。エラーコードがENOENT、EACCESS(アクセス許可が拒否された)、ENAMETOOLONGなどのいずれであっても、falseを返します。
[ -e "$file" ]テストもして行うことができますls -Ld -- "$file" > /dev/null。その場合、情報がプログラムで簡単に使用できないが、失敗したls理由がわかりますstat()。
$ file=/var/spool/cron/crontabs/root
$ if [ ! -e "$file" ]; then echo does not exist; fi
does not exist
$ if ! ls -Ld -- "$file" > /dev/null; then echo stat failed; fi
ls: cannot access '/var/spool/cron/crontabs/root': Permission denied
stat failed
少なくともls、ファイルが存在しないために失敗したのではなく、失敗したことを教えてくれます。それは、ファイルが存在するかどうかを判別できないためです。[このコマンドは、単に問題を無視しました。
ではzshシェル、あなたがエラーコード照会することができる$ERRNO特別な失敗後の変数[、コマンド、および数は、使用していることを、デコード$errnosで特別な配列zsh/systemのモジュールを:
zmodload zsh/system
ERRNO=0
if [ ! -f "$file" ]; then
err=$ERRNO
case $errnos[err] in
("") echo exists, not a regular file;;
(ENOENT|ENOTDIR)
if [ -L "$file" ]; then
echo broken link
else
echo does not exist
fi;;
(*) syserror -p "can't tell: " "$err"
esac
fi
(の最新バージョンでビルドした場合$errnos、一部のバージョンでzshgccはサポートが壊れていました)。