2010-06-28 5 views
5

In uno script BASH, sto provando a rilevare se esiste un file. Il nome file si trova in una variabile ma il comando -e sembra non essere in grado di rilevare il file. Il codice seguente restituisce sempre "~/misc/attività/drupal_backup.sh non esiste"Script Bash -e non rileva il nome file in una variabile

filename="~/misc/tasks/drupal_backup.sh" 

if [ -e "$filename" ]; then 
    echo "$filename exists" 
else 
    echo "$filename does not exist" 
fi 

D'altra parte, il seguente codice rileva il file in modo corretto:

if [ -e ~/misc/tasks/drupal_backup.sh ]; then 
    echo "$filename exists" 
else 
    echo "$filename does not exist" 
fi 

perché questo sarebbe ? Come posso ottenerlo per rilevare il file quando il nome del file si trova in una variabile?

+1

Ritengo che '' 'sia una comodità della riga di comando che non dovrebbe essere utilizzata negli script. –

risposta

7

È interessante. Sostituendo $HOME per ~ funziona come rimuovere le virgolette dal compito.

Se si inserisce uno set -x nella parte superiore di quello script, si vedrà che la versione con le virgolette imposta il nome del file su ~/... che è ciò che è dato a -e. Se si rimuovono le virgolette, il nome file è impostato su /home/somebody/... espanso. Quindi nel primo caso, vedi:

+ [ -e ~/... ] 

e non gli piace. Nel secondo caso, si vede:

+ [ -e /home/somebody/... ] 

e fa lavoro.

Se lo si fa, senza la variabile, si vede:

+ [ -e /home/somebody/... ] 

e, sì, funziona.


Dopo un po 'di indagine, ho scoperto che in realtà è l'ordine in cui svolge la sua bash espansioni. Dalla pagina man bash:

L'ordine di espansione è: espansione delle parentesi graffe, espansione della tilde, un parametro variabile e sostituzione di espansione e comando aritmetica (fatto in maniera da sinistra a destra), suddivisione in parole, e percorso espansione.

Ecco perché non funziona, la variabile è sostituito dopo l'espansione tilde. In altre parole, nel punto in cui bash desidera espandere ~, non ce n'è uno. È solo dopo l'espansione variabile che la parola viene modificata in ~/... e non ci sarà più alcuna espansione di tilde.

Una cosa che si poteva fare è di cambiare la sua dichiarazione if a:

if [[ -e $(eval echo $filename) ]]; then 

Questa valuterà l'argomento $ nomefile due volte. La prima volta (con eval), non ci sarà ~ durante la fase di espansione tilde ma $filename verrà modificato in ~/... durante la fase di espansione delle variabili.

Quindi, nella seconda valutazione (quella eseguita come parte dello if), lo ~ sarà presente durante la fase di espansione tilde.

L'ho provato sul mio file .profile e sembra funzionare, vi suggerisco di confermare nel vostro caso particolare.

+0

Grazie! La semplice sostituzione di ~ con $ HOME ha funzionato perfettamente. – thornate

+1

Va notato che non si dovrebbe mai usare 'eval'. '~' è una bella abbreviazione per la modalità interattiva, ma dovrebbe essere presente negli script proprio per questa ragione. Molti script di init contengono qualcosa come '[-r ~/.profile] &&. ~/.profile', e non so se questo funziona se la directory home contiene spazi. Meglio usare $ HOME e citare tutte le variabili: 'filename =" $ HOME/misc/tasks/drupal_backup.sh "'. In questo caso, la quotazione non è richiesta, ma non è dannosa ed è più semplice citare semplicemente tutto a meno che non si sappia esattamente dove si possono tralasciare le virgolette. – Philipp

+0

@Phillipp, se hai intenzione di fare una dichiarazione generale come "non dovresti mai usare eval" in una meritocrazia, potresti voler pensare a fare un backup con il tuo ragionamento :-) – paxdiablo