Bash

“du -sh ”和“du -sh ./”有什麼區別?

  • September 30, 2021

du -sh *和有什麼區別du -sh ./*

注意:我感興趣的是*./*部分。

$ touch ./-c $'a\n12\tb' foo
$ 杜 -hs *
**0個
12 乙**
0 富
*共 0 個*

如您所見,該-c文件被用作選項du並且未報告(並且您看到該total行是因為du -c)。此外,被呼叫的文件a\n12\tb讓我們認為有文件被稱為ab.

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

這樣更好。至少這次-c不被視為一種選擇。

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

那就更好了。./前綴防止-c被視為一個選項,並且輸出中沒有before./表示b其中沒有b文件,但是有一個帶有換行符的文件(但有關進一步的題外話,請參見下面的1)。

在可能的情況下使用前綴是一種很好的做法./,如果沒有,並且對於任意數據,您應該始終使用:

cmd -- "$var"

或者:

cmd -- $patterns

如果cmd不支持--標記選項的結束,您應該將其作為錯誤報告給其作者(除非它是由選擇和記錄為 for echo)。

在某些情況下,./*可以解決無法解決的問題--。例如:

awk -f file.awk -- *

如果a=b.txt在目前目錄中呼叫了一個文件,則失敗(將 awk 變數設置a為,b.txt而不是告訴它處理該文件)。

awk -f file.awk ./*

沒有問題,因為./a不是有效的 awk 變數名,所以./a=b.txt不作為變數賦值。

cat -- * | wc -l

如果-在目前目錄中呼叫了一個文件,則失敗,因為它告訴cat從其標準輸入讀取(-對於大多數文本處理實用程序和cd/來說都是特殊的pushd)。

cat ./* | wc -l

沒關係,因為./-不是特別的cat

像:

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

計算包含foo錯誤的文件數,因為它假定文件名不包含換行符(wc -l計算換行符、grep每個文件的輸出以及文件名本身的輸出)。您應該改用:

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

(計算一個/字元的行數更可靠,因為每個文件名只能有一個)。

對於 recursive grep,等效的技巧是使用:

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

./*不過可能會有一些不需要的副作用。

cat ./*

每個文件再添加兩個字元,因此會讓您更快地達到參數+環境的最大大小的限制。有時您不希望./在輸出中報告它。像:

grep foo ./*

會輸出:

./a.txt: foobar

代替:

a.txt: foobar

進一步的題外話

1 . 在評論中的討論之後,我覺得我必須在這裡擴展它。

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

上面,./標記每個文件的開頭意味著我們可以清楚地辨識每個文件名的開始位置(at ./)和結束位置(在下一個./或輸出結束之前的換行符處)。

這意味著,與 ) 的輸出du ./*相反,du -- *可以可靠地解析 ) 的輸出,儘管在腳本中並不那麼容易。

但是,當輸出到終端時,文件名可能會以多種方式欺騙您:

  • 控製字元、轉義序列會影響事物的顯示方式。例如,\r將游標移動到行首,\b將游標向後、\e[C向前移動(在大多數終端中)……
  • 許多字元在終端上是不可見的,從最明顯的字元開始:空格字元。
  • 有些 Unicode 字元看起來與大多數字型中的斜線相同
$ printf '\u002f \u2044 \u2215 \u2571 \u29F8\n'
/ ⁄ ∕ ╱ ⧸

(查看它在瀏覽器中的執行方式)。

一個例子:

$ touch x 'x ' $'y\bx' $'x\n0\t.\u2215x' $'y\r0\t.\e[Cx'
$ ln x y
$ du -hs ./*
0       ./x
0       ./x
0       ./x
0       .∕x
0       ./x
0       ./x

很多,xy不見了。

當輸出到終端時,像 ls 這樣的一些工具GNU會用問號替換不可列印的字元(注意(U+2215) 是可列印的)。GNUdu沒有。

有一些方法可以讓它們顯露出來:

$ 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

在我們告訴我們的字元集是 ASCII之後,看看如何轉向。???``ls

$ du -hs ./* | LC_ALL=C sed -n l
0\t./x$
0\t./x $
0\t./x$
0\t.\342\210\225x$
0\t./y\r0\t.\033[Cx$
0\t./y\bx$

$標記行尾,因此我們可以發現"x"vs "x ",所有不可列印的字元和非 ASCII 字元都由反斜杠序列表示(反斜杠本身將用兩個反斜杠表示),這意味著它是明確的。那是 GNU sed,它在所有 POSIX 兼容的實現中應該是相同的,sed但請注意,一些舊的sed實現幾乎沒有那麼有用。

$ du -hs ./* | cat -vte
0^I./x$
0^I./x $
0^I./x$
0^I.M-bM-^HM-^Ux$

(不是標準的,但很常見,也cat -A有一些實現)。那個很有幫助,使用不同的表示,但不明確(例如"^I"<TAB>顯示相同)。

$ du -hs ./* | od -vtc
0000000   0  \t   .   /   x  \n   0  \t   .   /   x      \n   0  \t   .
0000020   /   x  \n   0  \t   . 342 210 225   x  \n   0  \t   .   /   y
0000040  \r   0  \t   . 033   [   C   x  \n   0  \t   .   /   y  \b   x
0000060  \n
0000061

那是標準的和明確的(並且從實施到實施是一致的),但不那麼容易閱讀。

你會注意到y上面從未出現過。這是一個完全不相關的問題,與du -hs *文件名無關,但應該注意:因為du報告磁碟使用情況,它不會報告已列出的文件的其他連結(du儘管列出硬連結時,並非所有實現的行為都如此在命令行上)。

引用自:https://unix.stackexchange.com/questions/110750