293 votes

Comment vérifier si un fichier existe dans un shell script

Je voudrais écrire un shell script qui vérifie si un certain fichier, archived_sensor_data.json existe, et si oui, le supprime. Suivant http://www.cyberciti.biz/tips/find-out-if-file-exists-with-conditional-expressions.html J'ai essayé ce qui suit :

[-e archived_sensor_data.json] && rm archived_sensor_data.json

Cependant, une erreur s'est produite

[-e: command not found

lorsque j'essaie d'exécuter le résultat test_controller script à l'aide de la balise ./test_controller commande. Qu'est-ce qui ne va pas dans ce code ?

5 votes

7 votes

Vous devez définir un ou plusieurs espaces entre le crochet ouvrant "[" et l'option "-e", de même qu'entre le nom du fichier et le crochet fermant "]".

2 votes

546voto

chris Points 87

Il manque un espace obligatoire entre la parenthèse et -e :

#!/bin/bash
if [ -e x.txt ]
then
    echo "ok"
else
    echo "nok"
fi

17 votes

J'ai finalement ajouté deux espaces vides, un après le crochet d'ouverture et un avant celui de fermeture : [ -e archived_sensor_data.json ] && rm archived_sensor_data.json . Le script semble fonctionner maintenant.

8 votes

Cela fonctionne également en utilisant if [ -e "$1" ] (argument d'entrée nom de fichier).

12 votes

La principale différence ici est le fait que vous utilisez le script "bash" au lieu du script "shell". Remarquez que la première ligne que vous avez ajoutée est #!/bin/bash, vous dites donc à la machine d'utiliser "bash" au lieu de sh. Parce que sh ne reconnaît pas l'argument "-e".

73voto

PhilipK Points 2790

Voici une méthode alternative utilisant ls :

(ls x.txt && echo yes) || echo no

Si vous voulez cacher toute sortie de ls donc vous ne voyez que oui ou non, redirigez stdout et stderr à /dev/null :

(ls x.txt >> /dev/null 2>&1 && echo yes) || echo no

19 votes

Ce code signifie : "si ls est réussi, il y a un tel fichier, sinon, il n'y en a pas". Si ls a échoué, cela ne signifie pas que le fichier est manquant. Il peut s'agir d'une autre erreur. Par exemple, créez un fichier dans le répertoire appartenant à Root et essayez de faire ls sous un utilisateur normal. Il échouera avec Permission denied ce qui n'est pas équivalent à l'inexistence du fichier.

5 votes

@Tigran C'est une bonne distinction à connaître, dans mon cas cela n'a pas d'importance, mais merci de le signaler.

24voto

Lefty G Balogh Points 762

La toile de fond de ma recommandation de solution est l'histoire d'un ami qui, bien dans la deuxième semaine de son premier emploi, a nettoyé la moitié d'un serveur de construction. Donc la tâche de base est de déterminer si un fichier existe, et si oui, de le supprimer. Mais il y a quelques rapides traîtres sur cette rivière :

  • Tout est un fichier.

  • Les scripts n'ont un réel pouvoir que s'ils résolvent des tâches générales.

  • Pour être général, nous utilisons des variables

  • Nous utilisons souvent -f force dans les scripts pour éviter une intervention manuelle

  • J'aime aussi -r recursive pour m'assurer que nous créons, copions et détruisons en temps voulu.

Considérons le scénario suivant :

Nous avons le fichier que nous voulons supprimer : filesexists.json

Ce nom de fichier est stocké dans une variable

<host>:~/Documents/thisfolderexists filevariable="filesexists.json"

Nous disposons également d'une variable de chemin pour rendre les choses plus flexibles.

<host>:~/Documents/thisfolderexists pathtofile=".."

<host>:~/Documents/thisfolderexists ls $pathtofile

filesexists.json  history20170728  SE-Data-API.pem  thisfolderexists

Alors voyons si -e fait ce qu'il est censé faire. Les fichiers existent-ils ?

<host>:~/Documents/thisfolderexists [ -e $pathtofile/$filevariable ]; echo $?

0

C'est le cas. La magie.

Cependant, que se passerait-il si la variable "fichier" était accidentellement évaluée à "rien" ?

<host>:~/Documents/thisfolderexists filevariable=""

<host>:~/Documents/thisfolderexists [ -e $pathtofile/$filevariable ]; echo $?

0

Quoi ? C'est censé revenir avec une erreur... Et c'est le début de l'histoire de comment ce dossier entier dossier a été supprimé par accident

Une alternative pourrait être de tester spécifiquement ce que nous comprenons comme étant un 'fichier'.

<host>:~/Documents/thisfolderexists filevariable="filesexists.json"

<host>:~/Documents/thisfolderexists test -f $pathtofile/$filevariable; echo $?

0

Donc le fichier existe...

<host>:~/Documents/thisfolderexists filevariable=""

<host>:~/Documents/thisfolderexists test -f $pathtofile/$filevariable; echo $?

1

Donc, ce n'est pas un fichier et peut-être, nous ne voulons pas supprimer ce répertoire entier.

man test a déclaré ce qui suit :

-b FILE

       FILE exists and is block special

-c FILE

       FILE exists and is character special

-d FILE

       FILE exists and is a directory

-e FILE

       FILE exists

-f FILE

       FILE exists and is a regular file

...

-h FILE

       FILE exists and is a symbolic link (same as -L)

9voto

T G Points 106

En interne, la commande rm doit de toute façon tester l'existence du fichier,
alors pourquoi ajouter un autre test ? Il suffit d'émettre

rm filename

et il aura disparu après ça, qu'il ait été là ou non.
Utilisez rm -f si vous ne voulez pas de messages sur des fichiers inexistants.

Si vous devez prendre des mesures si le fichier n'existe PAS, vous devez le vérifier vous-même. D'après votre exemple de code, ce n'est pas le cas ici.

1 votes

C'est en fait une réponse tout à fait valable pour la commande rm. Pour les autres commandes, je suggère plutôt de tester avec -e.

0 votes

Sauf que ce n'est pas ce que la question demande.

1 votes

C'est tout à fait ce que la question demande, si vous lisez le ensemble du site y compris la partie "... et (si c'est le cas) ... le supprime".

3voto

android developer Points 20939

Vous pouvez également utiliser stat :

stat /
  File: /
  Size: 4096            Blocks: 8          IO Block: 4096   directory
Device: fd01h/64769d    Inode: 2           Links: 26
Access: (0755/drwxr-xr-x)  Uid: (    0/    root)   Gid: (    0/    root)
Access: 2009-01-01 02:00:00.000000000 +0200
Modify: 2009-01-01 02:00:00.000000000 +0200
Change: 2009-01-01 02:00:00.000000000 +0200
 Birth: -

Sur un chemin qui n'existe pas, vous obtiendrez :

stat /aaa
stat: cannot stat '/aaa': No such file or directory

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X