GNU/Linux >> Linux Esercitazione >  >> Linux

Perché Nullglob non è predefinito?

Nella maggior parte delle shell nullglob non è l'impostazione predefinita. Ciò significa, ad esempio, se esegui questo comando

ls *

in una directory vuota, espanderà il * glob in un letterale * , invece di un elenco vuoto di argomenti. Ci sono modi per cambiare questo comportamento, in modo che * in una directory vuota restituirà una lista vuota di argomenti, che sembrerebbe più intuitiva.

Quindi, c'è un motivo per cui nullglob è disabilitato di default? Se sì, qual è il motivo?

Risposta accettata:

Il nullglob opzione (che BTW è un zsh invenzione, aggiunta solo anni dopo a bash (2.0 )) non sarebbe l'ideale in un certo numero di casi. E ls è un buon esempio:

ls *.txt

O il suo equivalente più corretto:

ls -- *.txt

Con nullglob on eseguirebbe ls senza argomenti trattati come ls -- . (elenca la directory corrente) se nessun file corrisponde, il che è probabilmente peggio che chiamare ls con un letterale *.txt come argomento.

Avresti problemi simili con la maggior parte delle utilità di testo:

grep foo *.txt

Cercherei foo su stdin se non è presente txt file.

Un'impostazione predefinita più ragionevole, e quella di csh, tcsh, zsh o fish 2.3+ (e delle prime shell Unix) è annullare del tutto il comando se il glob non corrisponde.

bash (dalla versione 3) ha un failglob opzione per questo (interessante per questa discussione, poiché contrariamente a ash , AT&T ksh o zsh , bash non supporta gli ambiti locali per le opzioni (sebbene ciò debba cambiare in 4.4), quell'opzione, se abilitata a livello globale, interrompe alcune cose come le funzioni di completamento bash).

Nota che csh e tcsh sono leggermente diversi da zsh , fish o bash -O failglob in casi come:

ls -- *.txt *.html

Dove è necessario che tutti i glob non corrispondano per annullare il comando. Ad esempio, se esiste un file txt e nessun file html, diventa:

ls -- file.txt

Puoi ottenere quel comportamento con zsh con setopt cshnullglob sebbene sia un modo più sensato per farlo in zsh sarebbe usare un glob come:

ls -- *.(txt|html)

In zsh e ksh93 , puoi anche applicare nullglob su base globale, che è un approccio molto più sano rispetto alla modifica di un'impostazione globale:

files=(*.txt(N))  # zsh
files=(~(N)*.txt) # ksh93

creerebbe un array vuoto se non c'è txt file invece di fallire il comando con un errore (o renderlo un array con un *.txt argomento letterale con altre shell).

Versioni di fish prima della 2.3 funzionava come bash -O nullglob ma dai un avviso quando interattivo quando un glob non ha corrispondenze. Dalla 2.3 funziona come zsh fatta eccezione per i glob usati in for , set o count .

Ora, nella nota sulla cronologia, il comportamento era effettivamente interrotto dalla conchiglia Bourne. Nelle versioni precedenti di Unix, il globbing veniva eseguito tramite il /etc/glob helper e quell'helper si sono comportati come csh :fallirebbe il comando se nessuno dei glob corrispondesse a nessun file e rimuoverebbe i glob senza corrispondenze in caso contrario.

Relazionato:Bash + come uscire dallo script secondario e dallo script principale in entrambe le volte?

Quindi la situazione in cui ci troviamo oggi è dovuta a una decisione sbagliata presa nella shell Bourne.

Si noti che la shell Bourne (e la shell C) è stata fornita con un'altra nuova funzionalità Unix:l'ambiente. Ciò significava espansione delle variabili (il suo predecessore aveva solo $1 , $2 … parametri posizionali). La shell Bourne ha anche introdotto la sostituzione dei comandi.

Un'altra cattiva decisione di progettazione della shell Bourne è stata quella di eseguire il globbing (e la divisione) sull'espansione delle variabili e la sostituzione dei comandi (possibilmente per la compatibilità con le versioni precedenti della shell Thompson dove echo $1 invocherebbe comunque /etc/glob se $1 conteneva caratteri jolly (era più simile all'espansione della macro del pre-processore, poiché nel valore espanso veniva nuovamente analizzato come codice shell)).

Il fallimento dei glob che non corrispondono significherebbe, ad esempio, che:

pattern='a.*b'
grep $pattern file

fallirebbe il comando (a meno che non ci siano alcuni a.whateverb file nella directory corrente). csh (che esegue anche il globbing su espansione variabile) in quel caso non riesce il comando (e direi che è meglio che lasciare un bug dormiente lì, anche se non è buono come non eseguire affatto il globbing come in zsh ).


Linux
  1. Perché Cd non è un programma?

  2. Linux – Perché usiamo Su – e non solo Su?

  3. Perché Find non accetta '-exec Cp {} Dir +'?

  4. Perché un lungo ritardo dopo il comando non trovato?

  5. Perché è Rm -rf e non Rmdir -rf?

Perché "cancella" non cancella l'intero schermo?

Perché `esce &` non funziona?

Perché Lpd non è abilitato per impostazione predefinita nella trasmissione?

script user-data (cloud-init) non in esecuzione su EC2

perché sftp rmdir non funziona?

perché eliminare la cronologia di bash non è sufficiente?