Bash

為什麼 ls -d 也列出文件,它記錄在哪裡?

  • December 9, 2015
  • 指定ls --directory a*時應僅列出以a*
  • 但它列出了以開頭的文件和目錄a

問題

  • 除了我認為我徹底看過的地方之外man,我在哪裡可以找到一些關於此的文件?info
  • 這僅在 BASH 中有效嗎?

a*and*a*語法由 shell 實現,而不是由命令ls實現。

當您鍵入

ls a*

在您的 shell 提示符下,shell 擴展a*為目前目錄中名稱以 . 開頭的現有所有文件的列表a。例如,它可能會擴展a*為序列a1 a2 a3,並將這些作為參數傳遞給ls. ls命令本身永遠不會看到*角色;它只看到三個參數a1,a2a3

出於萬用字元擴展的目的,“文件”指的是目前目錄中的所有實體。例如,a1可能是普通文件,a2可能是目錄,也a3可能是符號連結。它們都有目錄條目,shell 的萬用字元擴展並不關心這些條目所指的實體類型。

實際上,您可能遇到的所有 shell(bash、sh、ksh、zsh、csh、tcsh、…)都實現了萬用字元。細節可能會有所不同,但*匹配零個或多個字元和?匹配任何單個字元的基本語法是相當一致的。

特別是對於 bash,這記錄在 bash 手冊的“文件名擴展”部分;執行info bash並蒐索“文件名擴展”,或查看此處

這是由 shell 而不是單個命令完成的這一事實產生了一些有趣的(有時是令人驚訝的)後果。最好的一點是萬用字元處理對於(幾乎)所有命令都是一致的。如果 shell 不這樣做,不可避免地有些命令不會打擾,而其他命令會以作者認為“更好”的微妙不同的方式來做。(我認為 Windows 命令外殼有這個問題,但我對它還不夠熟悉,無法進一步評論。)

另一方面,很難編寫命令來重命名多個文件。如果你寫:

mv *.log *.log.bak

它可能會失敗,因為*.log.bak它是基於目前目錄中已經存在的文件進行擴展的。有一些命令可以做這種事情,但它們必須使用自己的語法來指定如何重命名文件。有些命令(如find)可以做自己的萬用字元擴展;你必須引用參數來抑制 shell 的擴展:

find . -name '*.txt' -print

shell 的萬用字元擴展完全基於命令行參數的語法和現有文件集。它不受命令含義的影響。例如,如果要將所有.log文件向上移動到父目錄,可以鍵入:

mv *.log ..

如果您忘記了..

mv *.log

並且目前目錄中恰好有兩個.log文件,它將擴展為:

mv one.log two.log

這將重命名one.log和破壞two.log

編輯:在 52 次投票、接受和 Guru 徽章之後,也許我實際上應該回答標題中的問題。

-dor--directory選項ls不會告訴它只列出目錄。它告訴它列出目錄本身,而不是它們的內容。如果您將目錄名稱作為參數提供給ls,預設情況下它將列出目錄的內容,因為這通常是您感興趣的內容。該-d選項告訴它僅列出目錄本身。這在與萬用字元結合使用時特別有用。如果您鍵入:

ls -l a*

ls將為您提供名稱以 開頭的每個文件的長列表,以及名稱以 開頭a每個目錄的內容a。如果您只想要文件和目錄的列表,每行一行,您可以使用:

ls -ld a*

這相當於:

ls -l -d a*

再次記住,ls命令永遠不會看到*角色。

至於記錄在哪裡,man ls將向您展示ls幾乎任何類 Unix 系統上的命令文件。在大多數基於 Linux 的系統上,該ls命令是 GNU coreutils 包的一部分;如果你有info命令,info ls或者info coreutils ls應該給你更權威和全面的文件。其他系統,如MacOS,可能使用不同版本的ls命令,可能沒有info命令;對於那些系統,使用man ls. 如果您使用的是 GNU coreutils 實現*,ls --help則會顯示一條相對*較短的使用消息(在我的系統上為 117 行) 。

是的,即使是專家也需要不時查閱文件。另請參閱這個經典笑話

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