212 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 ?

3 votes

5 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 "]".

1 votes

415voto

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

15 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.

5 votes

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

5 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".

47voto

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

8 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.

2 votes

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

14voto

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)

7voto

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".

0voto

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