Mi aspettavo di non ottenere alcun risultato.
Se nullglob
fosse il valore predefinito, molti comandi si comporterebbero in modo inaspettato, perché è (forse sfortunatamente) comune che i comandi trattino il caso di argomenti zero nomefile in un modo qualitativamente diverso rispetto al caso di uno o più argomenti nomefile.
Supponiamo che tu abbia abilitato nullglob
( shopt -s nullglob
) e ti trovi in una directory in cui nessun file corrisponde *.txt
. Quindi *.txt
si espanderà davvero nel nulla - non in un campo vuoto, ma in nessun campo - come previsto. Ma ciò avrebbe questi risultati:
ls *.txt
dovrebbe elencare tutti i file nella directory corrente (tranne i file nascosti), perché è ciò che ls
fa quando non si passa alcun argomento sul nome del file.
cat *.txt
leggerebbe dallo standard input , perché quando cat
non ha argomenti per il nome file, è come se lo avessi eseguito cat -
. Se in esecuzione in modo interattivo, rimane in attesa di input. Molti comandi si comportano in questo modo.
cp *.txt dest/
fallirebbe con l'errore cp: missing destination file operand after 'dest/'
. Questo non è un disastro, ma è confuso e abbastanza diverso dal silenzioso successo che è probabilmente desiderato.
file *.txt
e vari altri programmi senza un comportamento speciale per il caso di argomenti con zero nomefile, fallirebbero comunque con un messaggio di errore o di utilizzo quando nessuno viene passato.
- Anche i casi che sembrano intuitivamente come dovrebbero funzionare spesso non lo farebbero.
printf 'Got file: "%s"\n' *.txt
stamperebbe Got file: ""
invece di niente.
- L'incapacità accidentale di citare le occorrenze di
*
, ?
e [
che non sono destinate ad essere espanse dalla shell produrrebbe più spesso risultati ovviamente sbagliati, ma in modi che potrebbero essere difficili da capire. Ad esempio, se nessun nome di file nella directory corrente è iniziato con gedit
, allora apt list gedit*
(dove apt list 'gedit*'
era previsto) diventerebbe giusto apt list
ed elencherà tutti i pacchetti disponibili.
Quindi è bene non avere questo comportamento senza averlo richiesto. Probabilmente la situazione pratica più comune che in realtà è semplificata nullglob
è for f in *.txt
. Vedi anche questa domanda (a cui la risposta di Sergiy Kolodyazhnyy è collegata).
La domanda più difficile a cui rispondere è perché - failglob
dove è un errore di espansione avere un glob che non corrisponde a nessun file - non è l'impostazione predefinita in bash. Credo che la risposta di Sergiy Kolodyazhnyy capisca la ragione anche senza affrontarla direttamente. Mantenere i globs in espansione senza produrre un errore di espansione è (forse purtroppo) il comportamento standardizzato, ed è anche un comportamento tradizionale, e quindi previsto,. Sebbene bash non tenti di essere completamente conforme a POSIX a meno che non venga invocato con il nome sh
o non venga passata l' --posix
opzione, molte delle sue scelte progettuali anche quando non sono in modalità POSIX seguono POSIX direttamente. Hanno dovuto scegliere alcuni comportamenti e ci sono degli svantaggi associati all'andare contro le aspettative degli utenti.
Penso che questo sia l'aspetto meno storicamente influente della questione, quindi l'ho salvato per ultimo ... ma vale la pena ricordare che c'è qualcosa di un po 'concettualmente strano nel nullglob
comportamento.
nullglob
all'inizio sembra elegante perché, sintatticamente , tratta il caso di zero file corrispondenti non diversamente dal caso di uno, due o qualsiasi altro numero. I comandi che eseguiamo, per i quali i glob si espandono in argomenti, non tendono a trattarli allo stesso modo, come descritto sopra. Ma sintatticamente questo sembra giusto, che penso sia la motivazione della tua domanda.
Eppure, c'è un'altra, più sottile incoerenza che nullglob
non affronta - che in realtà amplifica. Il caso di caratteri zero globbing ("caratteri jolly") viene trattato in modo profondamente diverso da quello di uno, due o qualsiasi altro numero. Ad esempio, con shopt -s nullglob
, se ab?d?f
non corrisponde ad alcun file, viene rimosso; se ab?d
non corrisponde ad alcun file, viene rimosso; ma se ab
non corrisponde a nessun file (ovvero se non esiste un file il cui nome è esattamente ab
) non viene comunque rimosso. Certo, sarebbe un disastro se fosse rimosso, perché potrebbe non essere destinato a fare riferimento a un file esistente nella directory corrente; potrebbe anche non fare riferimento a un file. Ma questo elimina ancora ogni speranza di coerenza totale.
I tre comportamenti forniti da bash - il valore predefinito del trattamento dei glob che non corrispondono a nessun file come se non fossero globs e il loro passaggio non espanso, il comportamento che ti aspettavi di trattarli (se perdonerai questa strana svolta di frase) in quanto indica lo zero di tutti i file che corrispondono ( nullglob
) e il comportamento sicuro di considerarli errori ( failglob
): tutti rappresentano approcci diversi all'ambiguità inerente alla shell che non è in grado di sapere se una determinata parola è intesa come un nome del file. La shell esegue le sue espansioni senza conoscere il modo in cui i particolari comandi che chiami tratteranno i loro argomenti.
Questo è uno dei tanti casi di separazione delle preoccupazioni . Nei sistemi il cui design segue la filosofia Unix, ogni parte ha lo scopo di fare una cosa e farlo bene . La shell elabora il testo in comandi e argomenti e invoca quei comandi, molti dei quali sono esterni alla shell stessa. Questo tende ad essere molto più bello e versatile dei sistemi in cui i comandi esterni sono essi stessi responsabili dell'esecuzione di tali trasformazioni (come con i tradizionali processori di comandi in DOS e Windows). Ma ha i suoi lati negativi occasionali.
shopt -s nullglob
produrrà stringhe vuote per pattern senza eguali eshopt -u nullglob
(impostazione standard) produrrà il pattern stesso.