2013-11-24 18 views
8

Sto cercando di ottenere l'equivalente del seguente codice C nello script di shell.Come eseguire determinati comandi se un file NON esiste?

if(!exist) { 
    command; 
    command; 
} 
else { 
    command; 
    command; 
} 

Quello che sto cercando di fare più esattamente in questo script di shell è controllare se il file non esiste e quindi crearlo.

Anche io sono davvero dispiaciuto se questo è un duplicato di un'altra domanda, ma davvero non sapevo come cercarlo.

+2

Se sei interessato agli script di bash, un'ottima risorsa è http://www.tldp.org/LDP/abs/abs-guide.pdf –

+0

Grazie, amico! Beh, ad essere onesti ho pensato che questa sarebbe stata la parte corretta di Stack Exchange per rispondere a questo tipo di domande. –

+2

È il posto giusto. La tua domanda è sull'argomento qui, @Patrick shell scripting è esplicitamente [sull'argomento] (http://unix.stackexchange.com/help/on-topic). Le domande di scripting di shell SO si perdono molto facilmente nel rumore, puoi chiedere loro dove ti senti più a tuo agio. – terdon

risposta

14

È possibile utilizzare questo:

 
if [ ! -e "$file" ]; then 
     touch file 
else 
     ... 
fi 
+0

race-condition-city, c'è un modo per usare un flag, come 'touch -e file', che esce con 1 se il file esiste già? –

7
if [ ! -e "$path" ] 
then 
    touch -- "$path" 
fi 

Una versione più semplice sarebbe quella di semplicemente touch -- "$path" - si crea il file se non esiste, e solo aggiorna i tempi di accesso e modifica se esiste. Lo double dash (--) garantisce che è possibile creare il file anche se inizia con un trattino e sono necessari quotes attorno a $path.

+0

Grazie mille! Non posso accettare la soluzione perché non ho abbastanza reputazione –

16

Verificare se esiste un file è un'operazione molto comune. Per cercare domande pertinenti, utilizzare la barra di ricerca (in alto a destra). Ho lots of results con i termini "file di script bash esiste"

In ogni caso, si desidera che sia la test incorporato o il suo equivalente semantico [ ]:

[ ! -e your_file ] && >your_file 

o

test ! -e your_file && >your_file 

che sarà primo test che your_file non esiste (!) esiste (-e) e lo crea in questo caso.

Per ulteriori informazioni sui diversi test è possibile eseguire (diverso da -e), è possibile digitare:

help -m test | less 
+3

Puoi anche usare la valutazione di cortocircuito, come in '[-e tuo_file] || > your_file' – Useless

7

non lo fanno, non è solo a determinate condizioni gara, ma anche i [ -e /path/file ] controlli se è possibile eseguire un stat(2) su un file, restituirà false per motivi diversi, non solo perché il file non può esistere.

Un esempio è un collegamento simbolico a un file che non esiste o un file in una directory per cui non si dispone dell'autorizzazione alla ricerca.

Un approccio molto migliore consiste nell'utilizzare i contrassegni giusti per la chiamata di sistema open(2) qui, ovvero O_CREAT|O_EXCL. In questo modo, lo open() non riesce se il file non esiste già senza dover controllare più volte i tick di clock della CPU.

Con una shell Bourne simile:

if (set -C && : > "$file") 2> /dev/null; then 
    print '%s\n' "$file has been created 
else 
    print '%s\n' "It hasn't, possibly because it was already there" 
fi 

(set -C è quello di consentire la bandiera O_EXCL).

Inoltre, perché si desidera creare un file vuoto? È probabile che tu voglia archiviare qualcosa in quel file.Poi, basta farlo:

set -C 
{ 
    echo blah 
    other-commands that-generate-the-content 
} > "$file" 

Poi, quel gruppo comando viene eseguito solo se il file non esistesse già (ed è stato possibile crearlo).

Se si desidera verificare l'esistenza per il file, scrivere almeno:

[ -e "$file" ] || [ -L "$file" ] 

o

ls -d -- "$file" > /dev/null 2>&1 

se ti interessa potenzialmente essere un collegamento simbolico. Ciò restituirà comunque false se il file esiste ma non hai il diritto di verificarlo.


Ora, se si desidera una risposta più lunga e storica di test per il file esistenza:

Inizialmente, il comando test (in v7 Unix dove prima apparizione) had no -e (nor -h/-L option or -a unary) opzione.

Il modo di verificare l'esistenza del file era con ls. ls (con -d) elenca il file e segnala un errore (e restituisce lo stato di uscita false) se non riesce a cercare il file per un motivo o per un altro. Inizialmente, Unix non disponeva di collegamenti simbolici, ma al momento dell'introduzione, ls è stato modificato per fare un lstat(2) su un file anziché stat(2). Cioè, in caso di symlink ls restituisce informazioni sul file symlink stesso, non sul file nel percorso a cui punta il collegamento simbolico.

Un'opzione per test (aka [) per il test per il file "esistenza" è stato introdotto nel Korn shell test builtin. Era -a, non -e. -a è per accessibile (credo) che è un termine più accurato di esistente.

Non so quando o cosa ha introdotto -e, possibilmente POSIX. POSIX says che -e stato scelto sopra -a per evitare la possibile confusione con il -abinario operatore (ad e).

In entrambi i casi, sia -a sia -e tentare uno stat(2) sul file, non uno lstat(2). Cioè:

[ -e "$file" ] 

è equivalente a:

ls -Ld -- "$file" > /dev/null 2>&1 

Quindi, a rigor di termini, restituisce vero se, al momento del test è stato fatto, è stato possibile per cercare il percorso dopo aver risolto i link simbolici e se stat(2) non riesce, il motivo dell'errore viene ignorato.

stat potrebbe non riuscire se il file non esiste (ENOENT), ovvero se il file non esiste o esiste ma è un collegamento simbolico a un file che non esiste, ma anche per molte altre ragioni.Guardando the possible error codes of stat(2) dà alcune idee:

  • EACCESS: durante la risoluzione del percorso (e che può essere qualsiasi componente del percorso e nel percorso di qualsiasi link simbolico), non dovete ricerca il permesso per una directory componente (si noti che si può ancora avere accesso al file tramite un altro percorso).
  • ELOOP: impossibile risolvere il percorso a causa di troppi collegamenti simbolici risolti per arrivarci.
  • ENOTDIR. Per esempio su /etc/passwd/foo o un link simbolico ad esso.
+1

Affermare che è soggetto a condizioni di gara è prematuro. L'OP non ha specificato da dove proviene questo file, ed è possibile che lo script sia l'unica cosa che lo crea. Anche dire che '[-e/percorso/file]' non dovrebbe essere usato perché può fallire in modo errato non è un buon argomento. Se il test fallisce in modo errato e tenta di creare il file, il processo creerà un errore. Rimuovendo il test e utilizzando O_EXCL, il processo creerà un errore per lo stesso motivo per il test. Inoltre potrebbe essere un programma che crea il file, in cui 'set -C' non impedirà al programma di sovrascriverlo. – Patrick

+1

@Patrick. No se il file è un collegamento simbolico a un file inesistente in una directory esistente, '[-e" $ file "]' restituirà false, la creazione avrà esito positivo senza O_EXCL (che è dove è pericoloso come un utente malintenzionato può costringerti a creare file dove non si vorrebbe), e fallirebbe con O_EXCL (che implica no-follow). –

+0

Inoltre, potrebbe essere molto "prematuro" per l'OP. Potrebbe benissimo essere che esegue una sola istanza dello script alla volta, che nient'altro potrebbe scrivere su quel file, che il file si trova in un'area molto addomesticata dove solo un utente ha accesso in scrittura e che quell'utente non è mai coinvolto nel trattare con dati "stranieri/alieni/non controllati", ma su stackexchange, le risposte sono destinate a tutti, quindi IMO, il rischio dovrebbe essere indicato. E dato che quel metodo è più sicuro e meno costoso (solo una chiamata di sistema, anche se una forcella nel primo, nessun comando esterno eseguito), il metodo dovrebbe essere preferito. –

Problemi correlati