Comment puis-je savoir si un fichier régulier n'existe pas dans Bash?
J'ai utilisé le script suivant pour voir si un fichier existe:
#!/bin/bash
FILE=$1
if [ -f $FILE ]; then
echo "File $FILE exists."
else
echo "File $FILE does not exist."
fi
Quelle est la syntaxe correcte à utiliser si je veux seulement vérifier si le fichier n'existe pas ?
#!/bin/bash
FILE=$1
if [ $FILE does not exist ]; then
echo "File $FILE does not exist."
fi
17 réponses
La commandetest ([
ici) a un opérateur logique " not " qui est le point d'exclamation (similaire à beaucoup d'autres langues). Essayez ceci:
if [ ! -f /tmp/foo.txt ]; then
echo "File not found!"
fi
Test De Fichier Bash
-b filename
- bloquer le fichier spécial-c filename
- Fichier de caractères spéciaux-d directoryname
- Vérifier l'Existence du répertoire-e filename
- Vérifiez l'existence du fichier, quel que soit le type (nœud, répertoire, socket, etc.)-f filename
- Vérifiez l'existence d'un fichier régulier pas un répertoire-G filename
- vérifiez si le fichier existe et appartient à l'ID de groupe effectif-G filename set-group-id
- True si le fichier existe et est set-group-id-k filename
- peu collant-L filename
- lien symbolique -O filename
- Vrai si fichier existe et est détenue par l'uid effectif-r filename
- Vérifier si le fichier est lisible-S filename
- Vérifier si le fichier est prise-s filename
- Vérifier si le fichier est différent de zéro taille-u filename
- Vérifier si le fichier set-user-id bit est défini-w filename
- Vérifier si le fichier est accessible en écriture-x filename
- Vérifier si le fichier est exécutable
Comment utiliser:
#!/bin/bash
file=./file
if [ -e "$file" ]; then
echo "File exists"
else
echo "File does not exist"
fi
Une expression de test peut être annulée à l'aide de l'opérateur !
#!/bin/bash
file=./file
if [ ! -e "$file" ]; then
echo "File does not exist"
else
echo "File exists"
fi
, Vous pouvez annuler une expression avec "!":
#!/bin/bash
FILE=$1
if [ ! -f "$FILE" ]
then
echo "File $FILE does not exist"
fi
La man page man test
ou, de manière équivalente, man [
-- ou help test
ou help [
pour de l'intégré dans la commande bash.
[[ -f $FILE ]] || printf '%s does not exist!\n' "$FILE"
En outre, il est possible que le fichier soit un lien symbolique brisé, ou un fichier non régulier, comme par exemple un socket, un périphérique ou un fifo. Par exemple, pour ajouter une vérification des liens symboliques Brisés:
if [[ ! -f $FILE ]]; then
if [[ -L $FILE ]]; then
printf '%s is a broken symlink!\n' "$FILE"
else
printf '%s does not exist!\n' "$FILE"
fi
fi
Il convient de mentionner que si vous avez besoin d'exécuter une seule commande, vous pouvez abréger
if [ ! -f "$file" ]; then
echo "$file"
fi
À
test -f "$file" || echo "$file"
Ou
[ -f "$file" ] || echo "$file"
Je préfère faire le One-liner suivant, au format compatiblePOSIX shell:
$ [ -f "/$DIR/$FILE" ] || echo "$FILE NOT FOUND"
$ [ -f "/$DIR/$FILE" ] && echo "$FILE FOUND"
Pour quelques commandes, comme je le ferais dans un script:
$ [ -f "/$DIR/$FILE" ] || { echo "$FILE NOT FOUND" ; exit 1 ;}
Une fois que j'ai commencé à faire cela, j'utilise rarement la syntaxe entièrement typée!!
Pour tester l'existence du fichier, le paramètre peut être l'une des suivantes:
-e: Returns true if file exists (regular file, directory, or symlink)
-f: Returns true if file exists and is a regular file
-d: Returns true if file exists and is a directory
-h: Returns true if file exists and is a symlink
Tous les tests ci-dessous s'appliquent aux fichiers, répertoires et liens symboliques:
-r: Returns true if file exists and is readable
-w: Returns true if file exists and is writable
-x: Returns true if file exists and is executable
-s: Returns true if file exists and has a size > 0
Exemple de script:
#!/bin/bash
FILE=$1
if [ -f "$FILE" ]; then
echo "File $FILE exists"
else
echo "File $FILE does not exist"
fi
Vous devez faire attention à l'exécution de test
pour une variable non cotée, car elle peut produire des résultats inattendus:
$ [ -f ]
$ echo $?
0
$ [ -f "" ]
$ echo $?
1
La recommandation est généralement d'avoir la variable testée entourée de guillemets doubles:
#!/bin/sh
FILE=$1
if [ ! -f "$FILE" ]
then
echo "File $FILE does not exist."
fi
Il y a trois façons distinctes de le faire:
-
Annule le statut de sortie avec bash (aucune autre réponse n'a dit Cela):
if ! [ -e "$file" ]; then echo "file does not exist" fi
Ou:
! [ -e "$file" ] && echo "file does not exist"
-
Annule le test dans la commande de test
[
(c'est la façon dont la plupart des réponses ont été présentées auparavant):if [ ! -e "$file" ]; then echo "file does not exist" fi
Ou:
[ ! -e "$file" ] && echo "file does not exist"
-
Agir sur le résultat du test étant négatif (
||
au lieu de&&
):Seulement:
[ -e "$file" ] || echo "file does not exist"
Cela semble stupide (IMO), ne le faites pas utilisez-le sauf si votre code doit être portable dans le shell Bourne (comme le
/bin/sh
de Solaris 10 ou plus tôt) qui manquait l'opérateur de négation de pipeline(!
):if [ -e "$file" ]; then : else echo "file does not exist" fi
, Vous pouvez faire ceci:
[[ ! -f "$FILE" ]] && echo "File doesn't exist"
Ou
if [[ ! -f "$FILE" ]]; then
echo "File doesn't exist"
fi
Si vous voulez vérifier le fichier et le dossier à la fois, utilisez l'option -e
au lieu de -f
. -e
renvoie true pour les fichiers réguliers, les répertoires, les sockets, les fichiers spéciaux de caractères,les fichiers spéciaux de blocs, etc.
Dans
[ -f "$file" ]
La commande [
effectue un appel système stat()
(Pas lstat()
) 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 régulier ou d'un lien symbolique se résolvant éventuellement en un fichier régulier (ou du moins au moment du stat()
).
Toutefois, si elle retourne false (ou si [ ! -f "$file" ]
ou ! [ -f "$file" ]
return true), il y a beaucoup de possibilités différentes:
- le fichier n'existe pas
- le fichier existe mais n'est pas un fichier régulier
- le fichier existe mais vous n'avez pas l'autorisation de recherche dans 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 normal, mais vous n'avez pas l'autorisation de recherche sur certains des répertoires impliqués dans la résolution du lien symbolique.
- ... tout autre raison pour laquelle l'appel système
stat()
peut échouer.
En bref, il 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'appel système stat()
pour revenir avec un code d'erreur de ENOENT
(ENOTDIR
nous dit que l'un des composants du chemin n'est pas un répertoire est un autre cas où nous pouvons dire que le fichier n'existe pas par ce chemin). Malheureusement, la commande [
ne nous le fait pas savoir. Il retournera false si le code d'erreur est ENOENT, eAccess (permission refusé), ENAMETOOLONG ou toute autre chose.
Le [ -e "$file" ]
test peut également être effectué avec ls -Ld -- "$file" > /dev/null
. Dans ce cas, ls
vous dira Pourquoi le stat()
a échoué, bien que l'information ne puisse pas facilement être utilisée 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 c'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 zsh
shell, vous pouvez interroger le code d'erreur avec le $ERRNO
variable spéciale après la commande [
défaillante, et décoder ce nombre en utilisant le tableau spécial $errnos
dans le module 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;;
(*) echo "can't tell"; syserror "$err"
esac
fi
(méfiez-vous du $errnos
le support est cassé avec certaines versions de zsh
lorsqu'il est construit avec des versions récentes de gcc
).
Pour inverser un test, utilisez "!". C'est équivalent à l'opérateur logique " not " dans d'autres langues. Essayez ceci:
if [ ! -f /tmp/foo.txt ];
then
echo "File not found!"
fi
Ou écrit d'une manière légèrement différente:
if [ ! -f /tmp/foo.txt ]
then echo "File not found!"
fi
, Ou vous pouvez utiliser:
if ! [ -f /tmp/foo.txt ]
then echo "File not found!"
fi
, Ou, presing tous ensemble:
if ! [ -f /tmp/foo.txt ]; then echo "File not found!"; fi
Qui peut être écrit (en utilisant alors " et " opérateur:&&) comme:
[ ! -f /tmp/foo.txt ] && echo "File not found!"
Qui semble plus court comme ceci:
[ -f /tmp/foo.txt ] || echo "File not found!"
La chose test
peut aussi compter. Cela a fonctionné pour moi (basé sur Bash Shell: Vérifier le fichier existe ou non):
test -e FILENAME && echo "File exists" || echo "File doesn't exist"
Ce code fonctionne également .
#!/bin/bash
FILE=$1
if [ -f $FILE ]; then
echo "File '$FILE' Exists"
else
echo "The File '$FILE' Does Not Exist"
fi
Le moyen le plus simple
FILE=$1
[ ! -e "${FILE}" ] && echo "does not exist" || echo "exists"
Ce script shell fonctionne également pour trouver un fichier dans un répertoire:
echo "enter file"
read -r a
if [ -s /home/trainee02/"$a" ]
then
echo "yes. file is there."
else
echo "sorry. file is not there."
fi
Parfois, il peut être pratique d'utiliser && et || les opérateurs.
Comme dans (Si vous avez la commande "test"):
test -b $FILE && echo File not there!
Ou
test -b $FILE || echo File there!