GNU/Linux >> Znalost Linux >  >> Linux

Proč není Nullglob výchozí?

Ve většině shellů nullglob není výchozí. To znamená, že například spustíte tento příkaz

ls *

v prázdném adresáři rozbalí * glob na doslovný * místo na prázdný seznam argumentů. Existují způsoby, jak toto chování změnit, takže * v prázdném adresáři vrátí prázdný seznam argumentů, což by se zdálo intuitivnější.

Existuje tedy důvod, proč nullglob je ve výchozím nastavení zakázáno? Pokud ano, jaký je ten důvod?

Přijatá odpověď:

nullglob možnost (která je mimochodem zsh vynález, jen o roky později přidán do bash (2.0 )) by v řadě případů nebylo ideální. A ls je dobrý příklad:

ls *.txt

Nebo jeho správnější ekvivalent:

ls -- *.txt

Pomocí nullglob on by spustil ls bez argumentu, který je považován za ls -- . (vypište aktuální adresář), pokud se žádné soubory neshodují, což je pravděpodobně horší než volání ls s doslovným *.txt jako argument.

Podobné problémy byste měli s většinou textových nástrojů:

grep foo *.txt

Hledal by foo na stdin, pokud neexistuje txt soubor.

Rozumnějším výchozím nastavením, jako je csh, tcsh, zsh nebo fish 2.3+ (a dřívějších unixových shellů), je úplně zrušit příkaz, pokud glob neodpovídá.

bash (od verze 3) má failglob možnost pro to (zajímavé pro tuto diskusi, protože na rozdíl od ash , AT&T ksh nebo zsh , bash nepodporuje místní rozsahy možností (ačkoli to se ve verzi 4.4 změní), tato možnost, když je povolena globálně, narušuje několik věcí, jako jsou funkce dokončování bash.

Všimněte si, že csh a tcsh se mírně liší od zsh , fish nebo bash -O failglob v případech jako:

ls -- *.txt *.html

Kde potřebujete, aby se všechny koule neshodovaly, aby byl příkaz zrušen. Pokud například existuje jeden soubor txt a žádný soubor html, bude to:

ls -- file.txt

Toto chování můžete získat pomocí zsh pomocí setopt cshnullglob i když rozumnější způsob, jak to udělat v zsh by bylo použít glob jako:

ls -- *.(txt|html)

V zsh a ksh93 , můžete také použít nullglob na základě jednotlivých zemí, což je mnohem rozumnější přístup než úprava globálního nastavení:

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

by vytvořilo prázdné pole, pokud neexistuje žádný txt namísto selhání příkazu s chybou (nebo vytvoření pole s jedním *.txt doslovný argument s jinými shelly).

Verze fish před 2.3 by fungovalo jako bash -O nullglob ale dávat varování, když je interaktivní, když globus nemá žádnou shodu. Od verze 2.3 funguje jako zsh kromě globů používaných v for , set nebo count .

Nyní, pokud jde o historii, chování bylo ve skutečnosti přerušeno od Bourne shellu. V předchozích verzích Unixu se globování provádělo prostřednictvím /etc/glob helper a ten se choval jako csh :příkaz by selhal, pokud by žádný z globů neodpovídal žádnému souboru, a jinak by globy bez shody odstranil.

Související:Bash + jak ukončit sekundární skript a hlavní skript v obou případech?

Takže situace, ve které jsme dnes, je způsobena špatným rozhodnutím učiněným v Bourneově shellu.

Všimněte si, že Bourne shell (a shell C) přišel s další novou funkcí Unixu:prostředím. To znamenalo variabilní rozšíření (jeho předchůdce měl pouze $1 , $2 … polohové parametry). Bourne shell také zavedl substituci příkazů.

Dalším špatným návrhovým rozhodnutím Bourne shellu bylo provést globování (a rozdělení) po expanzi proměnných a substituci příkazů (možná kvůli zpětné kompatibilitě s Thompsonovým shellem, kde echo $1 by stále vyvolávalo /etc/glob pokud $1 obsahoval zástupné znaky (tady to bylo spíše jako expanze makra preprocesoru, protože v rozšířené hodnotě byla znovu analyzována jako shell kód)).

Selhání koulí, které se neshodují, by například znamenalo:

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

by selhal příkaz (pokud tam nejsou nějaké a.whateverb soubory v aktuálním adresáři). csh (který také provádí globování při rozšiřování proměnné) v takovém případě příkaz selže (a řekl bych, že je to lepší, než tam nechat spící chybu, i když to není tak dobré, jako když globování neprovádíte vůbec jako v zsh ).


Linux
  1. Linux – proč používáme Su – a nejen Su?

  2. Proč je výchozí vidlice mechanismu vytváření procesu?

  3. Linux – Proč Setuid nefunguje?

  1. Proč „ukončit &“ nefunguje?

  2. Proč není LPD ve výchozím nastavení při přenosu povoleno?

  3. Proč je to Rm -rf a ne Rmdir -rf?

  1. Skript uživatelských dat (cloud-init) se na EC2 nespouští

  2. proč nefunguje sftp rmdir?

  3. Fedora 25 standardně NEPOUŽÍVÁ wayland!