GNU/Linux >> Linux Esercitazione >  >> Linux

La differenza tra "du -sh *" e "du -sh ./*"?

Qual è la differenza tra du -sh * e du -sh ./* ?

Nota:quello che mi interessa è il * e ./* parti.

Risposta accettata:

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

Come puoi vedere, il -c il file è stato preso come opzione per du e non è riportato (e vedi il total riga a causa di du -c ). Inoltre, il file chiamato an12tb ci sta facendo pensare che ci siano dei file chiamati a e b .

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

Va meglio. Almeno questa volta -c non è considerata un'opzione.

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

È anche meglio. Il ./ prefisso impedisce -c dall'essere preso come opzione e dall'assenza di ./ prima di b nell'output indica che non c'è nessun b file lì dentro, ma c'è un file con un carattere di nuova riga (ma vedi sotto per ulteriori digressioni su questo).

È buona norma utilizzare il ./ prefisso quando possibile, e in caso contrario e per dati arbitrari, dovresti sempre usa:

cmd -- "$var"

oppure:

cmd -- $patterns

Se cmd non supporta -- per segnare la fine delle opzioni, dovresti segnalarlo come bug al suo autore (tranne quando è per scelta e documentato come per echo ).

Ci sono casi in cui ./* risolve problemi che -- no. Ad esempio:

awk -f file.awk -- *

fallisce se è presente un file chiamato a=b.txt nella directory corrente (imposta la variabile awk a a b.txt invece di dirgli di elaborare il file).

awk -f file.awk ./*

Nessun problema perché ./a non è un nome di variabile awk valido, quindi ./a=b.txt non viene considerata come un'assegnazione variabile.

cat -- * | wc -l

fallisce se c'è un file chiamato - nella directory corrente, come dice a cat per leggere dal suo stdin (- è speciale per la maggior parte delle utilità di elaborazione del testo e per cd /pushd ).

cat ./* | wc -l

va bene perché ./- non è speciale per cat .

Cose come:

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

per contare il numero di file che contengono foo sono sbagliati perché presuppone che i nomi dei file non contengano caratteri di nuova riga (wc -l conta i caratteri di nuova riga, quelli emessi da grep per ogni file e quelli nei nomi dei file stessi). Dovresti usare invece:

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

(contando il numero di / caratteri è più affidabile in quanto può essercene solo uno per nome file).

Per grep ricorsivo , il trucco equivalente è usare:

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

./* potrebbe avere alcuni effetti collaterali indesiderati però.

cat ./*

aggiunge altri due caratteri per file, quindi ti farebbe raggiungere prima il limite della dimensione massima di argomenti + ambiente. E a volte non vuoi quel ./ da riportare in output. Come:

grep foo ./*

Verrebbe prodotto:

./a.txt: foobar

invece di:

a.txt: foobar

Ulteriori digressioni

. Sento di doverlo approfondire qui, seguendo la discussione nei commenti.

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

Sopra, quel ./ contrassegnare l'inizio di ogni file significa che possiamo identificare chiaramente dove inizia ogni nome di file (in ./ ) e dove finisce (alla nuova riga prima del successivo ./ o alla fine dell'output).

Correlati:come aggiungere la sottodirectory bin della prima directory in GOPATH a PATH?

Ciò significa che l'output di du ./* , contrariamente a quello di du -- * ) può essere analizzato in modo affidabile, anche se non così facilmente in uno script.

Quando l'output va a un terminale, tuttavia, ci sono molti altri modi in cui un nome di file può ingannarti:

  • I caratteri di controllo, le sequenze di escape possono influenzare il modo in cui le cose vengono visualizzate. Ad esempio, r sposta il cursore all'inizio della riga, b sposta il cursore indietro, e[C avanti (nella maggior parte dei terminali)...

  • molti caratteri sono invisibili su un terminale a partire da quello più ovvio:il carattere spazio.

  • Ci sono caratteri Unicode che hanno lo stesso aspetto della barra nella maggior parte dei caratteri

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

(guarda come va nel tuo browser).

Un esempio:

$ 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

Un sacco di x 's ma y manca.

Alcuni strumenti come GNU ls sostituirà i caratteri non stampabili con un punto interrogativo (notare che (U+2215) è stampabile) quando l'output va a un terminale. GNU du no.

Ci sono modi per farli rivelare:

$ 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

Guarda come passato a ??? dopo aver detto a ls che il nostro set di caratteri era ASCII.

$ du -hs ./* | LC_ALL=C sed -n l0t./x$0t./x $0t./x$0t.342210225x$0t./anno0t.
Linux
  1. Differenza tra 2>&-, 2>/dev/null, |&, &>/dev/null E>/dev/null 2>&1?

  2. Qual è la differenza tra Sudo Su – e Sudo Su –?

  3. La differenza tra .exrc e .vimrc?

  4. La differenza tra '$ . Foo' E '$ ./foo'??

  5. La differenza tra Nss e Pam?

La differenza tra più, meno e la maggior parte dei comandi

Qual è la differenza tra /sbin/nologin e /bin/false?

La differenza tra /opt e /usr/local?

La differenza tra collegamenti simbolici e hard?

Qual è la differenza tra ls e l?

Qual è la differenza tra unlink e rm?