Dans
[ -f "$file" ]
la [
commande effectue un stat()
(pas lstat()
) appel système sur le chemin stocké dans $file
et renvoie true si cet appel système réussit et que le type de fichier renvoyé par stat()
est " normal ".
Donc, si [ -f "$file" ]
renvoie true, vous pouvez dire que le fichier existe et qu'il s'agit d'un fichier normal ou d'un lien symbolique qui se résout finalement en un fichier normal (ou du moins c'était au moment de lastat()
).
Cependant, si elle renvoie false (ou si [ ! -f "$file" ]
ou ! [ -f "$file" ]
retourne true), il existe de nombreuses possibilités différentes:
- le fichier n'existe pas
- le fichier existe mais n'est pas un habitué fichier (peut être un périphérique, fifo, répertoire, socket ...)
- le fichier existe mais vous ne disposez pas des droits de recherche sur le répertoire parent
- le fichier existe mais ce chemin d'accès est trop long
- le fichier est un lien symbolique vers un fichier standard, mais vous n'avez pas l'autorisation de recherche sur certains des répertoires impliqués dans la résolution du lien symbolique.
- ... toute autre raison pour laquelle l'
stat()
appel système peut échouer.
Bref, ce devrait être:
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
Pour savoir avec certitude que le fichier n'existe pas, nous aurions besoin de l' stat()
appel système pour retourner avec un code d'erreur de ENOENT
( ENOTDIR
nous indique que l'un des composants du chemin n'est pas un répertoire est un autre cas où nous pouvons dire que le fichier ne l'est pas exister par ce chemin). Malheureusement,[
commande ne nous le fait pas savoir. Il retournera faux si le code d'erreur est ENOENT, EACCESS (autorisation refusée), ENAMETOOLONG ou autre.
Le [ -e "$file" ]
test peut également être effectué avec ls -Ld -- "$file" > /dev/null
. Dans ce cas, ls
vous dira pourquoi l' stat()
échec, bien que les informations ne puissent pas être facilement utilisées par programme:
$ 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
Au moins ls
me dit que ce n'est pas parce que le fichier n'existe pas qu'il échoue. C'est parce qu'il ne peut pas dire si le fichier existe ou non. La [
commande a simplement ignoré le problème.
Avec le zsh
shell, vous pouvez interroger le code d'erreur avec la $ERRNO
variable spéciale après la [
commande en échec et décoder ce nombre à l'aide du $errnos
tableau spécial du zsh/system
module:
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
(attention, le $errnos
support a été rompu avec certaines versions de zsh
lors de sa construction avec des versions récentes degcc
).