2015-06-23 17 views
6

Al momento ho questo script bash (che si trova nella mia home directory, cioè, /home/fusion809/ e io sono in esecuzione come root, come è necessario per le linee icona di copiatura):Come posso verificare se esiste un file o una directory di file in bash?

cd /home/fusion809/Pictures/Icon* 

declare -a A={Arch,Debian,Fedora,Mageia,Manjaro,OpenSUSE} 
declare -a B={Adwaita,Faenza,gnome,Humanity} 

for i in $A; do 
    for j in $B; do 
    if test -e /usr/share/icons/$j/scalable ; else 
     mkdir /usr/share/icons/$j/scalable/ 
    fi 
    if test -e /usr/share/icons/$j/scalable/$i.svg ; else 
     cp -a $i*.svg /usr/share/icons/$j/scalable/$i.svg 
    fi 
    done 
done 

Quello che voglio questo script per fare è copiare le icone dalla mia directory Pictures/Icons and logos alle sottodirectory del tema scalable (specificato in $B) in /usr/share/icons. Prima di farlo, tuttavia, mi piacerebbe creare una directory scalable in queste sottodirectory di temi se non esiste già. Il problema è che la parte else dei condizionali non viene letto correttamente, come continuo a ricevere questo errore:

./copyicon.sh: line 8: syntax error near unexpected token `else' 
./copyicon.sh: line 8: ` if test -e /usr/share/icons/$j/scalable ; else' 

Se vi state chiedendo il motivo per cui il test -e ... al condizionale si basa su un libro di testo sulla bash scripting I ho seguito

risposta

6

Controllo file e/o directory esistenza

Per verificare se un file esiste in , si utilizza l'operatore -f. Per le directory, utilizzare -d. Esempio di utilizzo:

$ mkdir dir 
$ [ -d dir ] && echo exists! 
exists! 
$ rmdir dir 
$ [ -d dir ] && echo exists! 
$ touch file 
$ [ -f file ] || echo "doesn't exist..." 
$ rm file 
$ [ -f file ] || echo "doesn't exist..." 
doesn't exist... 

Per ulteriori informazioni, è sufficiente eseguire man test.

Una nota su -e, questo operatore di test controlla se esiste un file. Anche se questo può sembrare una buona scelta, è meglio usare -f che restituirà false se il file non è un file normale. /dev/null ad esempio è un file ma non un file normale. Avere il check return true è indesiderato in questo caso.

Una nota sulle variabili

Assicurarsi di citare variabili troppo, una volta che si dispone di uno spazio o di qualsiasi altro carattere speciale contenuta in una variabile può avere effetti collaterali indesiderati. Quindi quando si verifica l'esistenza di file e directory, avvolgere il file/dir tra virgolette. Qualcosa come [ -f "/path/to/some/${dir}/" ] funzionerà mentre il seguente potrebbe fallire se c'è uno spazio in dir: [ -f /path/to/some/${dir}/ ].

Fissaggio l'errore di sintassi

Si verifica un errore di sintassi nelle istruzioni di controllo. Un bash if clausola è strutturato nel modo seguente:

if ...; then 
    ... 
fi 

o opzionale con una clausola else:

if ...; then 
    ... 
else 
    ... 
fi 

Non si può omettere la clausola di then. Se si desidera utilizzare solo la clausola else, si dovrebbe annullare la condizione. Con conseguente codice seguente:

if [ ! -f "/usr/share/icons/$j/scalable" ]; then 
    mkdir "/usr/share/icons/$j/scalable/" 
fi 

Qui aggiungiamo un punto esclamativo (!) per capovolgere la valutazione dell'espressione. Se l'espressione è true, la stessa espressione preceduta da ! restituirà false e viceversa.

+0

Modifica 'test -e ...' per 'test [-d ...]' restituisce: ./copyicon.sh: riga 8: errore di sintassi vicino a un token imprevisto 'else ' ./copyicon.sh: line 8: 'test [-d/usr/share/icons/$ j/ridimensionabile]; else ' – BH2017

+0

Questo perché la tua sintassi è sbagliata. Aggiornerò la risposta – ShellFish

+0

Per "negare la condizione" intendete che il punto esclamativo (!) Restituisce true se la directory non esiste ma è falsa se esiste? – BH2017

3

Non è possibile saltare il poi parte della dichiarazione se, soluzione più semplice sarebbe quella di negare solo alla prova

if [[ ! -e /usr/share/icons/${j}/scalable ]] ; then 
    mkdir /usr/share/icons/${j}/scalable/ 
fi 
if [[ ! -e /usr/share/icons/${j}/scalable/${i}.svg ]] ; then 
    cp -a ${i}*.svg /usr/share/icons/${j}/scalable/${i}.svg 
fi 

ho lasciato con -e (esiste), ma si potrebbe considera l'utilizzo di -d per le directory o -f per i file e alcuni errori di gestione per catturare elementi (ad esempio /usr/share/icons/$ j/scalable/ esiste, ma è un file e non una directory per qualsiasi motivo.) Ho anche notato che nel codice originale si sta tentando potenzialmente di copiare più file in uno:

L'ho lasciato in questo modo nel mio esempio, nel caso in cui si è certi che sia sempre un solo file e intenzionalmente lo si rinomini. Altrimenti suggerirei solo di specificare una directory di destinazione.

+1

Buona risposta, continuate così. – ShellFish

+0

ottima risposta, grazie. –

Problemi correlati