Im
[ -f "$file" ]
Der [
Befehl führt einen stat()
(nicht lstat()
) Systemaufruf für den in gespeicherten Pfad aus $file
und gibt true zurück , wenn dieser Systemaufruf erfolgreich ist und der von zurückgegebene Dateityp stat()
" normal " ist.
Wenn also [ -f "$file" ]
true zurückgegeben wird, können Sie feststellen, dass die Datei vorhanden ist und eine reguläre Datei oder ein Symlink ist, der schließlich in eine reguläre Datei aufgelöst wird (oder zumindest zum Zeitpunkt der stat()
).
Wenn jedoch false zurückgegeben wird (oder if [ ! -f "$file" ]
oder ! [ -f "$file" ]
true zurückgegeben wird), gibt es viele verschiedene Möglichkeiten:
- Die Datei existiert nicht
- Die Datei existiert, ist aber keine reguläre Datei (kann ein Gerät, ein FIFO, ein Verzeichnis, ein Socket sein ...)
- Die Datei ist vorhanden, Sie haben jedoch keine Suchberechtigung für das übergeordnete Verzeichnis
- Die Datei ist vorhanden, aber der Pfad für den Zugriff ist zu lang
- Die Datei ist ein Symlink zu einer regulären Datei, Sie haben jedoch keine Suchberechtigung für einige der Verzeichnisse, die an der Auflösung des Symlinks beteiligt sind.
- ... jeder andere Grund, warum der
stat()
Systemaufruf fehlschlagen kann.
Kurz gesagt sollte es sein:
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
Um sicher zu sein, dass die Datei nicht existiert, benötigen wir die stat()
Systemaufruf mit dem Fehlercode ENOENT
(gibt an ENOTDIR
, dass eine der Pfadkomponenten kein Verzeichnis ist, ein weiterer Fall, in dem wir feststellen können, dass die Datei nicht vorhanden ist) zurückkehren existieren auf diesem Weg). Leider [
lässt uns der Befehl das nicht wissen. Es wird false zurückgegeben, unabhängig davon, ob der Fehlercode ENOENT, EACCESS (Berechtigung verweigert), ENAMETOOLONG oder etwas anderes ist.
Der [ -e "$file" ]
Test kann auch mit durchgeführt werdenls -Ld -- "$file" > /dev/null
. In diesem Fall ls
erfahren Sie, warum dies stat()
fehlgeschlagen ist, obwohl die Informationen nicht einfach programmgesteuert verwendet werden können:
$ 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
Zumindest ls
sagt mir, dass es nicht daran liegt, dass die Datei nicht existiert. Dies liegt daran, dass nicht festgestellt werden kann, ob die Datei vorhanden ist oder nicht. Der [
Befehl hat das Problem einfach ignoriert.
Mit der zsh
Shell können Sie den Fehlercode mit der $ERRNO
speziellen Variablen nach dem fehlgeschlagenen [
Befehl abfragen und diese Nummer mithilfe des $errnos
speziellen Arrays in der dekodierenzsh/system
Modul :
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
(Vorsicht, die $errnos
Unterstützung wurde bei einigen Versionen von unterbrochen, zsh
wenn sie mit neueren Versionen von erstellt wurden.gcc
)