Perché le virgolette sono necessarie per l'argomento dei file quando si chiama questo script Bash?


13

Sono abbastanza nuovo negli script di Bash. Ho un "testscript", che ho usato come base per uno script più avanzato / utile:

#!/bin/bash
files=$1
for a in $files
do
    echo "$a"
done

Quando lo chiamo senza virgolette, prende solo un file in una directory:

testscript *.txt

Ma quando lo chiamo tra virgolette funziona correttamente e seleziona tutti i file di testo:

testscript '*.txt'

Cosa sta succedendo qui?


Per essere molto, molto chiaro, il modo giusto per risolvere questo problema è quello di eseguire for a in "$@"; do(o for a; do) nella tua sceneggiatura, lasciando così il trauma alla shell esterna, non tralasciare le virgolette.
Charles Duffy,


Vale la pena dare un'occhiata. guide.bash.academy
vascowhite,

Risposte:


29

Quando si chiama un programma

testscript *.txt

quindi la shell esegue l'espansione e calcola tutti i valori. Quindi potrebbe effettivamente chiamare il tuo programma come

testscript file1.txt file2.txt file3.txt file4.txt

Ora il tuo programma guarda solo $1e quindi funziona solo file1.txt.

Citando sulla riga di comando si passa la stringa letterale *.txtallo script, ed è quello in cui è memorizzata $1. Il tuo forloop quindi lo espande.

Normalmente useresti "$@"e non $1in script come questo.

Questo è un "gotcha" per le persone che provengono dallo scripting CMD, in cui la shell dei comandi non fa globbing (come è noto) e passa sempre la stringa letterale.


6
Solo per chiarire (per le persone diverse dall'autore della risposta di cui sopra), l'uso "$@"(in contrapposizione a $@o $1 $2 $3) causerà la citazione di ogni nome di file "file1.txt" "file2.txt"ecc. Per file1.txtquesto non ha senso, ma se lo hai my file.txt, la citazione è fondamentale per impedire la shell analizzando per trasformarlo in due nomi di file, uno con nome mye uno con nome file.txt. Cita sempre l'input dell'utente e l'espansione globale per non essere molto infelice un giorno.
Seth Robertson,

2
E questo non è solo teorico: una volta Mac OS X è stato fornito con uno script di aggiornamento che non citava correttamente gli argomenti e alla fine ha eliminato le unità disco delle persone in alcune circostanze.
soffice

2
@fluffy, hai un link a riguardo?
Wildcard il

@Wildcard Purtroppo non sono riuscito a trovare alcun articolo a riguardo, ma è stata una grande novità nel mondo della tecnologia quando è successo. Voglio dire che è stato nel 2003/2004 o giù di lì, quando Apple stava ancora imparando a diventare un distributore UNIX.
soffice

1
@wildcard Ah, l'ho trovato! xlr8yourmac.com/OSX/itunes2_erased_drives.html - in realtà era uno script di aggiornamento di iTunes a essere il colpevole.
soffice

7

Senza virgolette la shell si espande *.txtprima di invocare lo script, quindi $1è solo il primo file che viene espanso. Tutti i txtfile sono argomenti per il tuo script a quel punto (supponendo che non ce ne siano troppi).

Con le virgolette quella stringa viene passata senza essere espansa nello script, il che quindi consente di forfare l'espansione, come speri.

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.