web-dev-qa-db-fra.com

Comment savoir si un fichier standard 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 existe pas?

#!/bin/bash

FILE=$1     
if [ $FILE does not exist ]; then
   echo "File $FILE does not exist."
fi
3002
Bill the Lizard

La commande test ([ here) a un opérateur logique "non" qui est le point d'exclamation (similaire à de nombreuses autres langues). Essaye ça:

if [ ! -f /tmp/foo.txt ]; then
    echo "File not found!"
fi
4213
John Feminella

Test de fichier Bash

-b filename - Bloquer le fichier spécial
-c filename - Fichier de caractères spéciaux
-d directoryname - Vérifie l'existence du répertoire.
-e filename - Vérifie l'existence du fichier, quel que soit son type (nœud, répertoire, socket, etc.)
-f filename - Vérifie que le fichier n'existe pas et qu'il ne s'agit pas d'un répertoire
-G filename - Vérifie si le fichier existe et appartient à l'ID du groupe effectif
-G filename set-group-id - Vrai si le fichier existe et est set-group-id
-k filename - Bit collant
-L filename - Lien symbolique
-O filename - Vrai si le fichier existe et appartient à l'ID utilisateur effectif
-r filename - Vérifier si le fichier est lisible
-S filename - Vérifier si le fichier est un socket
-s filename - Vérifie si la taille du fichier est différente de zéro
-u filename - Vérifier si le bit set-user-id du fichier est activé
-w filename - Vérifier si le fichier est 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 
599
BlueCacti

Vous pouvez nier une expression avec "!":

#!/bin/bash
FILE=$1

if [ ! -f "$FILE" ]
then
    echo "File $FILE does not exist"
fi

La page de manuel appropriée est man test ou, de manière équivalente, man [ - ou help test ou help [ pour la commande intégrée bash.

277
unbeknown
[[ -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 standard, comme par exemple. une prise, un appareil ou fifo. Par exemple, pour ajouter une vérification aux liens symboliques rompus:

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
128
guns

Il convient de mentionner que si vous devez 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"
95
Elazar Leibovich

Je préfère faire le one-liner suivant, en POSIX Format compatible avec 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!

64
J. M. Becker

Pour tester l'existence d'un fichier, le paramètre peut être l'un des suivants:

-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 classiques:

-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
51
SD.

Tu peux le faire:

[[ ! -f "$FILE" ]] && echo "File doesn't exist"

ou

if [[ ! -f "$FILE" ]]; then
    echo "File doesn't exist"
fi

Si vous souhaitez vérifier le fichier et le dossier, utilisez l’option -e au lieu de -f. -e renvoie true pour les fichiers normaux, les répertoires, les sockets, les fichiers spéciaux de caractères, les fichiers spéciaux de bloc, etc.

34
Jahid

Vous devez faire attention à exécuter test pour une variable non citée, car elle pourrait produire des résultats inattendus:

$ [ -f ]
$ echo $?
0
$ [ -f "" ]
$ echo $?
1

Il est généralement recommandé de placer la variable testée entre guillemets:

#!/bin/sh
FILE=$1

if [ ! -f "$FILE" ]
then
   echo "File $FILE does not exist."
fi
31
artdanil

Il existe trois façons distinctes de procéder:

  1. Annulez 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"
    
  2. Annulez le test à l'intérieur de la commande de test [ (c'est ainsi que la plupart des réponses ont déjà été présentées):

    if [ ! -e "$file" ]; then
        echo "file does not exist"
    fi
    

    Ou:

    [ ! -e "$file" ] && echo "file does not exist"
    
  3. Agissez sur le résultat du test négatif (|| au lieu de &&):

    Seulement:

    [ -e "$file" ] || echo "file does not exist"
    

    Cela semble idiot (IMO), ne l'utilisez pas sauf si votre code doit être portable dans Bourne Shell (comme le /bin/sh de Solaris 10 ou une version antérieure) auquel il manquait l'opérateur de négation de pipeline (!) :

    if [ -e "$file" ]; then
        :
    else
        echo "file does not exist"
    fi
    
22
user2350426

Dans

_[ -f "$file" ]
_

la commande _[_ effectue un appel système stat() (et non lstat()) sur le chemin stocké dans _$file_ et renvoie true si cet appel système aboutit et que le type du fichier renvoyé par stat() est " normal ".

Ainsi, si _[ -f "$file" ]_ renvoie true, vous pouvez savoir que le fichier existe et qu'il s'agit d'un fichier normal ou d'un lien symbolique éventuellement résolu en fichier normal (ou du moins qu'il l'était au moment de la stat()).

Cependant, s'il retourne false (ou si _[ ! -f "$file" ]_ ou _! [ -f "$file" ]_ renvoie true), les possibilités sont nombreuses:

  • le fichier n'existe pas
  • le fichier existe mais n'est pas un fichier normal (peut être un périphérique, fifo, répertoire, socket ...)
  • le fichier existe mais vous n'avez pas le droit de rechercher dans le répertoire parent
  • le fichier existe mais le chemin pour y accéder est trop long
  • le fichier est un lien symbolique vers un fichier normal, mais vous n'avez pas le droit de recherche sur certains des répertoires impliqués dans la résolution du lien symbolique.
  • ... toute autre raison pour laquelle l'appel système stat() peut échouer.

En bref, cela 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() à renvoyer avec un code d'erreur de ENOENT (ENOTDIR nous indique qu'un des composants du chemin n'est pas un répertoire. peut dire que le fichier n'existe pas par ce chemin). Malheureusement, la commande _[_ ne nous le dit pas. Il retournera false si le code d'erreur est ENOENT, EACCESS (autorisation refusée), ENAMETOOLONG ou autre.

Le test _[ -e "$file" ]_ peut également être effectué avec _ls -Ld -- "$file" > /dev/null_. Dans ce cas, ls vous expliquera pourquoi la stat() a échoué, 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
_

ls au moins 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 shell zsh, vous pouvez interroger le code d'erreur avec la variable spéciale _$ERRNO_ après la commande _[_ défaillante et décoder ce nombre à l'aide du tableau spécial _$errnos_ dans le _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 support $errnos_ A ÉTÉ INTERROMPU AVEC CERTAINES VERSIONS DE zsh LORSQU’IL A ÉTÉ CONSTRUIT AVEC DES VERSIONS RÉCENTES DE gcc ).

20
Stephane Chazelas

Pour inverser un test, utilisez "!". Cela équivaut à l'opérateur logique "pas" dans d'autres langues. Essaye ça:

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, présidant tous ensemble:

if ! [ -f /tmp/foo.txt ]; then echo "File not found!"; fi

Ce qui peut être écrit (en utilisant then "et" operator: &&) comme:

[ ! -f /tmp/foo.txt ] && echo "File not found!"

Ce qui ressemble plus court à ceci:

[ -f /tmp/foo.txt ] || echo "File not found!"
10
user2350426

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
9
Lemon Kazi

La chose test peut aussi compter. Cela a fonctionné pour moi (basé sur Bash Shell: Le fichier existe ou pas):

test -e FILENAME && echo "File exists" || echo "File doesn't exist"
8
android developer

Le plus simple

FILE=$1
[ ! -e "${FILE}" ] && echo "does not exist" || echo "exists"
6
lancerex

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
5
Simmant

parfois, il peut être utile 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!
3
André

Si vous voulez utiliser test au lieu de [], vous pouvez utiliser ! pour obtenir la négation:

if ! test "$FILE"; then
  echo "does not exist"
fi
0
Mauro Zallocco

Vous pouvez également regrouper plusieurs commandes dans la même ligne.

[ -f "filename" ] || ( echo test1 && echo test2 && echo test3 )

ou

[ -f "filename" ] || { echo test1 && echo test2 && echo test3 ;}

Si le nom de fichier ne se ferme pas, la sortie sera

test1
test2
test3

Remarque: (...) s'exécute dans un sous-shell, {...;} s'exécute dans le même shell. La notation des accolades ne fonctionne que dans bash.

0
upteryx