GNU/Linux >> Znalost Linux >  >> Linux

Výsledek Ls *, Ls ** a Ls ***?

Vím, že používám příkaz ls zobrazí seznam všech adresářů. Ale co dělá ls * příkaz udělat? Použil jsem to a uvádí pouze adresáře. Má hvězdička před ls znamená, jak hluboko bude seznam adresářů?

Přijatá odpověď:

ls vypíše soubory a obsah adresářů, které jsou předávány jako argumenty, a pokud není zadán žádný argument, vypíše aktuální adresář. Lze mu také předat řadu voleb, které ovlivňují jeho chování (viz man ls pro podrobnosti).

Pokud ls je předán argument nazvaný * , vyhledá soubor nebo adresář s názvem * v aktuálním adresáři a vypsat jej jako kterýkoli jiný. ls nezachází s * znak jakýmkoli jiným způsobem než jakýmkoli jiným.

Pokud však ls * je shell příkazového řádku, to je kód v jazyce unixového shellu , pak shell rozbalí tento * podle jeho globování (také označované jako Generování názvu souboru nebo Rozšíření názvu souboru/cesty ) pravidla.

Zatímco různé shelly podporují různé globbingové operátory, většina z nich se shoduje na tom nejjednodušším * . * jako vzor znamená libovolný počet znaků, takže * jako glob se rozbalí na seznam souborů v aktuálních adresářích, které odpovídají tomuto vzoru. Existuje však výjimka, že úvodní tečka (. ) znak v názvu souboru musí být explicitně shodný, takže * ve skutečnosti expanduje na seznam souborů a adresářů, které nezačínají . (v lexikálním pořadí).

Například, pokud aktuální adresář obsahuje soubory s názvem . , .. , .foo , -l a foo bar , * bude shellem rozšířen na dva argumenty, které se předají ls :-l a foo bar , takže to bude, jako byste napsali:

ls -l "foo bar"

nebo

'ls' "-l" foo bar

Což jsou tři způsoby, jak spustit úplně stejný příkaz. Ve všech 3 případech ls příkaz (který bude pravděpodobně spuštěn z /bin/ls z vyhledávání adresářů uvedených v $PATH ) budou předány tyto 3 argumenty:„ls“, „-l“ a „foo bar“.

Mimochodem, v tomto případě ls bude zacházet s prvním (přesně řečeno druhým ) jeden jako možnost.

Nyní, jak jsem řekl, různé shelly mají různé globbingové operátory. Před několika desetiletími zsh představil **/ operator¹, což znamená, že odpovídá jakékoli úrovni podadresářů, zkratka pro (*/)# a ***/ což je stejné až na to, že při sestupu v adresářích následuje symbolické odkazy.

Před několika lety (červenec 2003, ksh93o+ ), ksh93 se rozhodl zkopírovat toto chování, ale rozhodl se, že bude nepovinné a pokryje pouze ** případ (nikoli *** ). Také, zatímco ** samotný nebyl v zsh speciální ² (myšleno totéž jako * jako v jiných tradičních shellech od ** znamená libovolný počet znaků následovaný libovolným počtem znaků), v ksh93 ** znamená totéž jako **/* (tedy jakýkoli soubor nebo adresář pod aktuálním (kromě skrytých souborů)³.

bash zkopírován ksh93 o několik let později (únor 2009, bash 4.0), se stejnou syntaxí, ale nešťastným rozdílem:bash's ** bylo jako zsh „s *** , to znamená, že to bylo sledování symbolických odkazů při návratu do podadresářů, což obecně není to, co chcete, aby to dělalo, a může to mít nepříjemné vedlejší účinky. V bash-4.3 to bylo částečně opraveno v tom, že se stále dodržovaly symbolické odkazy, ale tam se rekurze zastavila. Ve verzi 5.0 to bylo plně opraveno.

yash přidán ** ve verzi 2.0 v roce 2008, povoleno pomocí extended-glob volba. Jeho implementace je blíže k zsh 's v tom ** sám není zvláštní. Ve verzi 2.15 (2009) přidal *** jako v zsh a dvě vlastní přípony:.** a .*** pro zahrnutí skrytých adresářů při opakování (v zsh , D kvalifikátor glob (jako v **/*(D) ) bude zvažovat skryté soubory a adresáře, ale pokud chcete pouze procházet skryté adresáře, ale ne rozbalovat skryté soubory, potřebujete ((*|.*)/)#* nebo **/[^.]*(D) ).

Související:Simulace ořezového obvodu produkující neočekávaný výsledek?

Rybí skořápka také podporuje ** . Stejně jako předchozí verze bash , následuje symbolické odkazy při sestupu do adresářového stromu. V tomto shellu však **/* není totéž jako ** . ** je spíše rozšířením * které mohou zahrnovat několik adresářů. V fish , **/*.c bude odpovídat a/b/c.c ale ne a.c , zatímco a**.c bude odpovídat a.c a ab/c/d.c a zsh ‘s **/.* například musí být napsáno .* **/.* . Tady, *** je chápán jako ** následovaný * tedy stejně jako ** .

tcsh také přidán globstar možnost ve V6.17.01 (květen 2010) a podporuje obě ** a *** à la zsh .

Tedy v tcsh , bash a ksh93 , (když je povolena odpovídající možnost (globstar )) nebo fish , ** rozbalí všechny soubory a adresáře pod aktuálním souborem a *** je stejný jako ** pro fish , symbolický odkaz procházející ** pro tcsh s globstar a stejné jako * v bash a ksh93 (ačkoli není vyloučeno, že budoucí verze těchto shellů budou také procházet symbolické odkazy).

Výše jste si všimli, že je potřeba zajistit, aby žádné z rozšíření nebylo interpretováno jako možnost. Pro to byste udělali:

ls -- *

Nebo:

ls ./*

Existují nějaké příkazy (nezáleží na tom pro ls ), kde je vhodnější druhý, protože i s -- některé názvy souborů mohou být ošetřeny speciálně. To je případ - pro většinu textových nástrojů cd a pushd a názvy souborů, které obsahují = znak pro awk například. Před ./ všem argumentům odstraňuje jejich zvláštní význam (alespoň pro případy uvedené výše).

Je třeba také poznamenat, že většina shellů má řadu možností, které ovlivňují chování globbingu (např. zda jsou soubory s tečkami ignorovány nebo ne, pořadí řazení, co dělat, pokud neexistuje žádná shoda…), viz také $FIGNORE parametr v ksh

Také v každém shellu kromě csh , tcsh , fish a zsh , pokud vzor koule neodpovídá žádnému souboru, vzor je předán jako nerozbalený argument, což způsobuje zmatek a možná i chyby. Pokud například v aktuálním adresáři není žádný neskrytý soubor

ls *

Ve skutečnosti zavolá ls se dvěma argumenty ls a * . A protože neexistuje vůbec žádný soubor, tak žádný s názvem * buď se zobrazí chybová zpráva od ls (ne shell) jako:ls: cannot access *: No such file or directory , o kterém je známo, že si lidé myslí, že to byl ls to ve skutečnosti rozšiřovalo koule.

Problém je ještě horší v případech jako:

rm -- *.[ab]

Pokud neexistuje *.a ani *.b soubor v aktuálním adresáři, pak můžete skončit smazáním souboru s názvem *.[ab] omylem (csh , tcsh a zsh by nahlásil žádnou shodu chyba a nezavolá rm (a fish nepodporuje [...] zástupné znaky)).

Pokud chcete předat doslovný * na ls , musíte uvést, že * znak nějakým způsobem jako v ls * nebo ls '*' nebo ls "*" . V shellech podobných POSIXu lze globování úplně zakázat pomocí set -o noglob nebo set -f (poslední nefunguje v zsh pokud není v sh /ksh emulace).

Související:Php:mysql_field_seek — Nastavte ukazatel výsledku na zadaný offset pole

.


Linux
  1. Příkaz Linux Sed:Použití a příklady

  2. Jak zkontrolovat verzi OS a Linuxu

  3. Najděte největší soubory a adresáře v Linuxu

  1. Rozdíl mezi Nss a Pam?

  2. Výzva a příslib velkých dat

  3. Jaký je rozdíl mezi ls a l?

  1. Jaký je rozdíl mezi InnoDB a MyISAM?

  2. Rozdíl mezi [[ $a ==Z* ]] a [ $a ==Z* ]?

  3. Jaký je rozdíl mezi unlink a rm?