Comando per visualizzare un messaggio arbitrario se esiste un file specifico


11

Esiste un comando per visualizzare il messaggio "Sì" se esiste un file specifico? Non è necessario fornire funzionalità se il file non esiste.

Risposte:


25

Usa questo semplice bash one-liner:

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

Il -econtrollo restituisce true se FILENAMEesiste, indipendentemente da ciò che è (file, directory, collegamento, dispositivo, ...).

Se vuoi solo controllare i file regolari, usa -finvece, come ha detto @Arronical .


18
[ -e FILENAME ] && echo Yes
Zeb McCorkle,

@ZebMcCorkle Correct, anche questo funziona. Potresti postarlo come risposta separata.
Byte Commander

3
Se FILENAMEè un'espansione variabile o contiene caratteri speciali, non dimenticare di citarla. ad esempio in uno script, [ -e "$1" ] && echo Yes.
Peter Cordes,

@PeterCordes se stai usando bash puoi usare [[e ]]invece di citare la variabile.
Holloway,

1
@Holloway: sì, ma a volte è necessario scrivere script portatili che richiedono solo POSIX sh. Questo è il motivo per cui ho dato una versione sicura di questo invece di ridimensionarlo e aumentare la risposta bash. Si noti inoltre che non è un problema per citare le espansioni all'interno [[ ]], citando sempre è una buona abitudine per i principianti che non ricordano le regole speciali per all'interno [[ ]]dell'operatore o per i contesti aritmetici.
Peter Cordes,

10

Puoi usare questo semplice script:

#!/bin/bash

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

Salva come file-exists.sh. Quindi, nel Terminale, digitare chmod +x file-exists.sh.

Usalo come: ./file-exists.sh FILEdove lo sostituisci FILEcon il file che vuoi controllare, ad esempio:

./file-exists.sh file.txt

Se file.txtesiste, Yesverrà stampato sul Terminale e il programma uscirà con lo stato 0 (successo). Se il file non esiste, non verrà stampato nulla e il programma uscirà con lo stato 1 (errore).

Se sei curioso di sapere perché ho incluso il exitcomando, continua a leggere ...


Che succede con il exitcomando?

exitprovoca la normale interruzione del processo. Ciò significa sostanzialmente: interrompe la sceneggiatura. Accetta un parametro facoltativo (numerico) che sarà lo stato di uscita dello script che lo ha chiamato.

Questo stato di uscita consente agli altri script di utilizzare il tuo file-existsscript ed è il loro modo di sapere se il file esiste o meno.

Un semplice esempio che lo mette in pratica è questo script (salvalo come 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

Fare il solito chmod +x file-exists-cli.she quindi eseguirlo: ./file-exists-cli.sh. Vedrai qualcosa del genere:

Il file esiste ( exit 0):

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

Il file non esiste ( exit 1):

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

2
Bene, ma citerai riferimenti variabili come "$1". Se contiene uno spazio bianco, si romperà senza virgolette e possono accadere altre cose brutte.
Joe,

9

Nella shell bash dalla riga di comando.

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

Questo utilizza l'operatore condizionale bash -fe controlla se il file esiste ed è un file normale. Se si desidera verificare eventuali file inclusi directory e collegamenti, utilizzare -e.

Questa è un'ottima risorsa per i condizionali bash.


1
Perché le doppie parentesi graffe?
Byte Commander

1
Non sono un fan del testsuo formato originale, so che è eccessivo, ma è mia abitudine.
Arronical,

7
@ByteCommander: le doppie parentesi graffe sono generalmente migliori delle singole parentesi graffe. Fanno parte della sintassi della shell (invece di invocare il [comando, che di solito chiama un built-in). Correggono le incoerenze e i comportamenti stupidi della versione single brace. Il [builtin rimane per compatibilità, ma non vedo alcun buon motivo per usarlo nel nuovo codice bash. (Se hai bisogno di scrivere script compatibili con POSIX che possono essere eseguiti su shell antiche o qualcosa del genere, è diverso.)
Nick Matteo

@kundor: Principalmente d'accordo, comunque, per essere onesti, "di [solito chiama un builtin" è dubbio. type -a [per me elenca "shell builtin", quindi " /usr/bin/[."
wchargin,

1
@wchargin: temo di non capire a cosa stai arrivando. I tuoi typerisultati sembrano confermare ciò che ho detto, no?
Nick Matteo,

5

Il comando più breve per fare ciò che vuoi è:

test -e FILENAME && echo Yes

test -everificherà se il nome fornito esiste nel file system. (È possibile utilizzare test -fper limitare solo ai file normali. Vedere man testdi più.)

Se la condizione fornita testrestituisce true, restituisce uno stato di uscita corretto (altrimenti restituisce uno stato di errore). Combiniamo i due comandi usando &&, il che significa "esegui il comando successivo se il comando precedente è uscito con uno stato di successo". Il comando successivo stampa semplicemente Yessull'output standard; nel caso di una shell interattiva, sul terminale.

Ciò evita il materiale testuale aggiuntivo di ifun'affermazione, ma fornisce lo stesso risultato. L'uso &&(o il suo opposto ||) per unire i comandi funziona bene quando è coinvolto un solo comando. Se vuoi fare di più che eseguire un singolo comando in risposta allo stato di uscita di un singolo comando, l'utilizzo della ifsintassi diventa rapidamente molto più leggibile.

Come già sottolineato in altre risposte, il ifcostrutto di stile equivalente sarebbe:

if test -e FILENAME; then echo Yes; fi

o in alternativa:

if test -e FILENAME
then
    echo Yes
fi

Per questi scopi, [e testsono equivalenti, tranne che [richiede una risoluzione ].


4

Per eliminare questo tipo di domanda ci sono molti modi, ed eccone un altro: usa il findcomando con -execflag. Il percorso del file può essere diviso in due parti find /etcche imposta la directory e -name FILENAMEche specifica il nome del file (duh!). -maxdepthcontinuerà a findfunzionare /etcsolo con la directory e non scenderà nelle sottodirectory

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:~$ 

Un altro modo, tramite stat:

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

E in alternativa tramite 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'

O una breve alternativa alla riga di comando:

 python -c "from os.path import exists; print 'Yes' if exists('/etc/fstab') else '' "
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.