GNU/Linux >> Znalost Linux >  >> Linux

Rozdíl mezi „du -sh *“ a „du -sh ./*“?

Jaký je rozdíl mezi du -sh * a du -sh ./* ?

Poznámka:Co mě zajímá, je * a ./* části.

Přijatá odpověď:

$ touch ./-c $'an12tb' foo
$ du -hs *
0       a
12      b
0       foo
0       total

Jak můžete vidět, -c soubor byl použit jako možnost du a není hlášeno (a vidíte total řádek kvůli du -c ). Také soubor s názvem an12tb nás nutí si myslet, že existují soubory zvané a a b .

$ du -hs -- *
0       a
12      b
0       -c
0       foo

To je lepší. Tentokrát alespoň -c není brána jako možnost.

$ du -hs ./*
0       ./a
12      b
0       ./-c
0       ./foo

to je ještě lepší. ./ prefix zabraňuje -c z toho, že je brána jako možnost, a absence ./ před b ve výstupu označuje, že není žádné b soubor tam, ale je tam soubor se znakem nového řádku (ale další odbočky k tomu viz níže).

Je dobrým zvykem používat ./ prefix, pokud je to možné, a pokud ne, a pro libovolná data, měli byste vždy použití:

cmd -- "$var"

nebo:

cmd -- $patterns

Pokud cmd nepodporuje -- chcete-li označit konec možností, měli byste to nahlásit jako chybu jejímu autorovi (kromě případů, kdy je to na vlastní žádost a zdokumentováno jako u echo ).

Existují případy, kdy ./* řeší problémy, které -- ne Například:

awk -f file.awk -- *

selže, pokud existuje soubor s názvem a=b.txt v aktuálním adresáři (nastavuje proměnnou awk a do b.txt místo toho, aby mu řekl, aby soubor zpracoval).

awk -f file.awk ./*

Nemá problém, protože ./a není platný název proměnné awk, takže ./a=b.txt se nebere jako přiřazení proměnné.

cat -- * | wc -l

selže, pokud existuje soubor s názvem - v aktuálním adresáři, jak to říká cat číst z jeho stdin (- je speciální pro většinu nástrojů pro zpracování textu a pro cd /pushd ).

cat ./* | wc -l

je v pořádku, protože ./- není speciální pro cat .

Věci jako:

grep -l -- foo *.txt | wc -l

spočítat počet souborů, které obsahují foo jsou chybné, protože předpokládá, že názvy souborů neobsahují znaky nového řádku (wc -l počítá znaky nového řádku, které vypíše grep pro každý soubor a soubory v samotných názvech souborů). Místo toho byste měli použít:

grep -l foo ./*.txt | grep -c /

(počítá se počet / znaků je spolehlivější, protože pro každý soubor může být pouze jeden).

Pro rekurzivní grep , ekvivalentní trik je použít:

grep -rl foo .//. | grep -c //

./* může mít některé nežádoucí vedlejší účinky.

cat ./*

přidá dva další znaky na soubor, takže byste dříve dosáhli limitu maximální velikosti argumentů + prostředí. A to někdy nechcete ./ vykazovat ve výstupu. Jako:

grep foo ./*

Výstup:

./a.txt: foobar

místo:

a.txt: foobar

Další odbočky

. Cítím, že to zde musím rozvést a sledovat diskuzi v komentářích.

$ du -hs ./*
0       ./a
12      b
0       ./-c
0       ./foo

Nad tím ./ označení začátku každého souboru znamená, že můžeme jasně identifikovat, kde každý název souboru začíná (na ./ ) a kde končí (na novém řádku před dalším ./ nebo konec výstupu).

Související:Jak přidat podadresář bin prvního adresáře v GOPATH do PATH?

To znamená, že výstup du ./* , na rozdíl od du -- * ) lze spolehlivě analyzovat, i když ne tak snadno ve skriptu.

Když výstup jde do terminálu, existuje mnoho dalších způsobů, jak vás název souboru může oklamat:

  • Ovládací znaky, escape sekvence mohou ovlivnit způsob zobrazení věcí. Například r přesune kurzor na začátek řádku, b přesune kurzor zpět, e[C vpřed (ve většině terminálů)…

  • mnoho znaků je na terminálu neviditelných, počínaje tím nejviditelnějším:znakem mezery.

  • Existují znaky Unicode, které vypadají stejně jako lomítko ve většině písem

     $ printf 'u002f u2044 u2215 u2571 u29F8n'
     / ⁄ ∕ ╱ ⧸
    

(podívejte se, jak to chodí ve vašem prohlížeči).

Příklad:

$ touch x 'x ' $'ybx' $'xn0t.u2215x' $'yr0t.e[Cx'
$ ln x y
$ du -hs ./*
0       ./x
0       ./x
0       ./x
0       .∕x
0       ./x
0       ./x

Spousta x ‘s but y chybí.

Některé nástroje jako GNU ls by nahradilo netisknutelné znaky otazníkem (všimněte si, že (U+2215) lze tisknout), když výstup jde na terminál. GNU du ne.

Existují způsoby, jak je přimět, aby se odhalily:

$ ls
x  x   x?0?.∕x  y  y?0?.?[Cx  y?x
$ LC_ALL=C ls
x  x?0?.???x  x   y  y?x  y?0?.?[Cx

Podívejte se, jak obrátil na ??? poté, co jsme řekli ls že naše znaková sada byla ASCII.

$ du -hs ./* | LC_ALL=C sed -n l0t./x$0t./x $0t./x$0t.342210225x$0t./rok0t.
Linux
  1. Rozdíl mezi [[ $a ==Z* ]] a [ $a ==Z* ]?

  2. Jaký je rozdíl mezi Sudo Su – a Sudo Su –?

  3. Rozdíl mezi /opt a /usr/local?

  1. Rozdíl mezi .exrc a .vimrc?

  2. Rozdíl mezi „$ . Foo“ A „$ ./foo“??

  3. Rozdíl mezi /etc/crontab a crontab -e

  1. Rozdíl mezi získáváním zdrojů („.“ nebo „zdrojem“) a spouštěním souboru v Bash?

  2. Linux:Rozdíl mezi /dev/console, /dev/tty a /dev/tty0?

  3. Jaký je rozdíl mezi /tmp a /run?