Commande pour afficher un message arbitraire si un fichier particulier existe

11

Existe-t-il une commande pour afficher le message «Oui» si un fichier particulier existe? Pas besoin de donner de fonctionnalité si le fichier n'existe pas.

James
la source

Réponses:

25

Utilisez cette simple doublure Bash:

if [ -e FILENAME ] ; then echo Yes ; fi

La -evérification est évaluée à true si elle FILENAMEexiste, quel qu'il soit (fichier, répertoire, lien, périphérique, ...).

Si vous souhaitez uniquement vérifier les fichiers normaux, utilisez -fplutôt, comme l' a dit @Arronical .

Byte Commander
la source
18
[ -e FILENAME ] && echo Yes
Zeb McCorkle
@ZebMcCorkle Correct, cela fonctionne aussi. Vous pouvez poster cela comme une réponse distincte.
Byte Commander
3
S'il FILENAMEs'agit d'une extension variable ou qui contient des caractères spéciaux, n'oubliez pas de la citer. par exemple dans un script, [ -e "$1" ] && echo Yes.
Peter Cordes
@PeterCordes si vous utilisez bash, vous pouvez utiliser [[et ]]au lieu de citer la variable.
Holloway
1
@ Hollow: yup, mais parfois vous devez écrire des scripts portables qui ne nécessitent que POSIX sh. C'est pourquoi j'ai donné une version sûre de cela au lieu de le diminuer et de voter pour la réponse bash. Notez également que ce n'est pas un problème de citer des extensions à l'intérieur [[ ]], toujours citer est une bonne habitude pour les débutants qui ne se souviennent pas des règles spéciales pour l'intérieur de l' [[ ]]opérateur ou pour les contextes arithmétiques.
Peter Cordes
10

Vous pouvez utiliser ce script simple:

#!/bin/bash

if [[ -f $1 ]]; then
    echo "Yes"
    exit 0
else
    exit 1
fi

Enregistrez-le sous file-exists.sh. Ensuite, dans le terminal, tapez chmod +x file-exists.sh.

Utilisez-le comme: ./file-exists.sh FILEoù vous remplacez FILEpar le fichier que vous souhaitez vérifier, par exemple:

./file-exists.sh file.txt

S'il file.txtexiste, Yessera imprimé sur le terminal et le programme quittera avec le statut 0 (succès). Si le fichier n'existe pas, rien ne sera imprimé et le programme quittera avec le statut 1 (échec).

Si vous êtes curieux de savoir pourquoi j'ai inclus la exitcommande, lisez la suite ...


Qu'est-ce qui se passe avec la exitcommande?

exitprovoque l'arrêt normal du processus. Ce que cela signifie, en gros: il arrête le script. Il accepte un paramètre facultatif (numérique) qui sera l'état de sortie du script qui l'a appelé.

Cet état de sortie permet à vos autres scripts d'utiliser votre file-existsscript et est leur façon de savoir si le fichier existe ou non.

Un exemple simple qui met cela à profit est ce script (enregistrez-le sous file-exists-cli.sh):

#!/bin/bash

echo "Enter a filename and I will tell you if it exists or not: "
read FILE
# Run `file-exists.sh` but discard any output because we don't need it in this example
./file-exists.sh $FILE &>> /dev/null
# #? is a special variable that holds the exit status of the previous command
if [[ $? == 0 ]]; then
    echo "$FILE exists"
else
    echo "$FILE does not exist"
fi

Faites l'habitude chmod +x file-exists-cli.shet puis exécutez: ./file-exists-cli.sh. Vous verrez quelque chose comme ceci:

Le fichier existe ( exit 0):

➜  ~ ./file-exists-cli.sh 
Enter a filename and I will tell you if it exists or not: 
booleans.py
booleans.py exists

Le fichier n'existe pas ( exit 1):

➜  ~ ./file-exists-cli.sh
Enter a filename and I will tell you if it exists or not: 
asdf
asdf does not exist
grooveplex
la source
2
Bien, mais tu citeras des références de variables comme "$1". S'il contient un espace blanc, il se cassera sans guillemets et d'autres mauvaises choses peuvent se produire.
Joe
9

Dans le shell bash sur la ligne de commande.

if [[ -f /path/to/file ]]; then echo "Yes"; fi

Cela utilise l'opérateur conditionnel bash -fet vérifie si le fichier existe et s'il s'agit d'un fichier normal. Si vous souhaitez tester des fichiers, y compris des répertoires et des liens, utilisez -e.

Ceci est une excellente ressource pour les conditionnels bash.

Arronical
la source
1
Pourquoi les doubles croisillons?
Byte Commander
1
Je ne suis pas fan de testson format d'origine, je sais que c'est exagéré, mais c'est une de mes habitudes.
Arronical
7
@ByteCommander: les accolades doubles sont généralement meilleures que les accolades simples. Ils font partie de la syntaxe du shell (au lieu d'appeler la [commande, qui appelle généralement une fonction intégrée). Ils corrigent les incohérences et les comportements stupides de la version à accolade simple. Le [builtin reste pour la compatibilité, mais je ne vois aucune bonne raison de l'utiliser dans le nouveau code bash. (Si vous avez besoin d'écrire des scripts compatibles POSIX pouvant s'exécuter sur d'anciens shells ou quelque chose du genre, c'est différent.)
Nick Matteo
@kundor: Généralement, cependant, pour être juste, " [appelle généralement un intégré" est douteux. type -a [pour moi liste "shell intégré", puis " /usr/bin/[."
wchargin
1
@wchargin: J'ai bien peur de ne pas comprendre à quoi vous voulez en venir. Vos typerésultats semblent corroborer ce que j'ai dit, non?
Nick Matteo
5

La commande la plus courte pour faire ce que vous voulez est:

test -e FILENAME && echo Yes

test -etestera si le nom donné existe dans le système de fichiers. (Vous pouvez utiliser test -fpour restreindre aux fichiers normaux uniquement. Voir man testpour en savoir plus.)

Si la condition donnée prend la valeur true, testrenvoie un état de sortie réussi (sinon, il renvoie un état d'échec). Nous combinons les deux commandes à l'aide de &&, ce qui signifie "exécuter la commande suivante si la commande précédente s'est terminée avec un état de réussite". La commande suivante imprime simplement Yessur la sortie standard; dans le cas d'un shell interactif, sur le terminal.

Cela évite le matériel textuel supplémentaire d'une ifdéclaration, mais donne le même résultat. Utiliser &&(ou son contraire ||) pour lier des commandes ensemble fonctionne bien lorsqu'une seule commande est impliquée. Si vous souhaitez faire plus qu'exécuter une seule commande en réponse à l'état de sortie d'une seule commande, l'utilisation de la ifsyntaxe devient rapidement beaucoup plus lisible.

Comme déjà souligné dans d'autres réponses, la ifconstruction de style équivalente serait:

if test -e FILENAME; then echo Yes; fi

Ou bien:

if test -e FILENAME
then
    echo Yes
fi

À ces fins, [et testsont équivalents, sauf que cela [nécessite une résiliation ].

un CVn
la source
4

Pour habiller ce type de question, il existe plusieurs façons, et en voici une autre: utilisez la findcommande avec -execindicateur. Le chemin d'accès au fichier peut être divisé en deux parties find /etcqui définit le répertoire et -name FILENAMEqui spécifie le nom du fichier (duh!). -maxdepthcontinuera à findtravailler /etcuniquement avec le répertoire et ne descendra pas dans les sous-répertoires

adminx@L455D:~$ find /etc -maxdepth 1  -name passwd -exec printf "YES\n" \;
YES
adminx@L455D:~$ find /etc -maxdepth 1  -name passwd1 -exec printf "YES\n" \;
adminx@L455D:~$ 

Une autre manière, via stat:

adminx@L455D:~$ stat /etc/passwd1 &>/dev/null && echo YES
adminx@L455D:~$ stat /etc/passwd &>/dev/null && echo YES
YES

Et alternativement via python:

>>> import os
>>> if os.stat('/etc/passwd'): 
...    print 'YES'
... 
YES
>>> if os.stat('/etc/passwd1'): 
...    print 'YES'
... 
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
OSError: [Errno 2] No such file or directory: '/etc/passwd1'

Ou une alternative courte en ligne de commande:

 python -c "from os.path import exists; print 'Yes' if exists('/etc/fstab') else '' "
Sergiy Kolodyazhnyy
la source