Linux

查找和符號連結

  • March 18, 2020

我正在瀏覽 find 的文件以更好地利用命令用法。

我正在閱讀說

GNU find 將以兩種方式之一處理符號連結;首先,它可以為您取消引用連結 - 這意味著如果遇到符號連結,它會檢查連結指向的文件,以查看它是否符合您指定的標準。其次,它可以檢查連結本身,以防您正在尋找實際連結。如果符號連結指向的文件也在您使用 find 命令搜尋的目錄層次結構中,那麼您可能看不出這兩種選擇之間有很大的區別。

預設情況下,find 在找到符號連結時會自行檢查它們(如果稍後遇到連結到的文件,它也會檢查)。

據我了解,如果我這樣做:

find -L -iname "*foo*"

這將遞歸搜尋目前目錄,當它遇到符號連結時,它會跟隨原始文件的連結。如果原始文件的名稱為 pattern *foo*,則報告前一個連結。

然而,情況似乎並非如此。我有

main-file
sl-file -> main-file

執行上面的命令find -L -iname "*main*"報告

./main-file

我期待著

./main-file # because it matches the criterion
./sl-file   # because the file points to matches the criterion

話雖如此,使用另一個測試就像-type我所期望的那樣工作。說我有這個:

main-file
dir/sl-file -> ../main-file

執行這個

find dir -type f

什麼都不返回。但是這個

find -L dir -type f

報告dir/sl-file

是什麼賦予了?

我看過這篇文章,說文件名不是文件屬性。這是我無法真正理解的事情。

Gnufind文件在術語上不像POSIX文件那樣嚴格。後者闡明了這一點,我將參考它。它沒有定義-iname,所以我將專注於-name. 我假設-iname被設計為類似-name,僅不區分大小寫。因此,我希望所有-name與 case 無關的屬性也適用-iname

這些是 POSIX 文件的相關部分:

find [-H|-L] path... [operand_expression...]

find實用程序應從由指定的每個文件遞歸地降低目錄層次結構path

$$ … $$. 每個path操作數都應按原樣進行評估,包括所有尾隨 <slash> 字元;層次結構中遇到的其他文件的所有路徑名應由目前路徑操作數的串聯、如果目前路徑操作數不是以 1 結尾的 <slash> 以及相對於路徑操作數的文件名組成。相對部分不應包含點或點-點組件,不包含尾隨 <slash> 字元,並且路徑名組件之間僅包含單個 <slash> 字元。

-name pattern

如果目前路徑名的基名pattern使用模式匹配表示法匹配,則主節點應評估為真

$$ … $$

-print

$$ … $$它會導致目前路徑名被寫入標準輸出。

定義

Basename

對於包含至少一個文件名的路徑名:路徑名中的最終文件名或唯一文件名。

$$ … $$

文件名

字節序列

$$ … $$用於命名文件。組成名稱的字節不應包含 <NUL> 或 <slash> 字元。$$ … $$文件名有時被稱為“路徑名組件”。$$ … $$

路徑名

用於標識文件的字元串。

$$ … $$它具有可選的開頭 <slash> 字元,後跟零個或多個由 <slash> 字元分隔的文件名。

所以-name對目前路徑名中的最終文件名感興趣;目前路徑名是一個字元串,用於標識目前文件。被誰使用?在這種情況下,由find. 從概念上講,路徑名可能與文件系統中的名稱無關。如果find使用某個字元串來標識文件,則該字元串稱為“路徑名”並-name使用它。

呼叫find . -printfind -L . -print。您將看到此特定呼叫使用的所有路徑名find。它們的最終文件名是-name您使用-name.


在您使用 and 的範例中main-filesl-file命令是find -L -iname "*main*". 最後有隱含-print,您觀察到的輸出來自-print. 你期望:

./main-file # because it matches the criterion
./sl-file   # because the file points to matches the criterion

但如果是這種情況,那就意味著-print給了你./main-fileand ./sl-file,所以這些是確切的路徑名,所以main-filesl-file是相應的基本名稱-name(或-iname)處理。

這不合適。這些基本名稱中只有一個與您使用的模式匹配 ( *main*)。這就是為什麼你只得到一個結果。指定-name "*main*"(或-iname "*main*")並期望./sl-file出現等同於期望sl-file匹配*main*

期望出現./main-file兩次是有道理的。前提是符號連結導致find將第二個路徑名從 更改./sl-file./main-file。然後兩個路徑名都將匹配*main*,並且都將列印為./main-file. 這不會發生。

如果您希望發生這種情況,請考慮一個bar指向/etc/fstab並放置在/tmp/foo/. 我們在foo目錄中。應該find -L .列印什麼(除了.)?您似乎希望此路徑名通過-name fstab測試,因此基本名稱必須是fstab. 另一方面,根據規則,路徑名必須以./(因為.是提供的路徑)開頭,並且不得包含點-點組件。沒有可以使用的合理且有意義的路徑名。怎麼辦?幸運的是,在這種情況下,該工具只列印./bar. 這是路徑名,它(作為字元串)與fstab.


很少有不使用符號連結但顯示其-name工作原理的範例:

cd /etc && find . -name . 2>/dev/null


儘管`.`事實上它的“真實”(特定的,在文件系統中)名稱是`etc`. `.`儘管在某些情況下任何目錄都可能存在,但它不會找到子目錄。
2. ```
cd /etc && find . -name etc 2&gt;/dev/null

它既沒有etc也沒有.。 3. 創建一個空的 FAT32 文件系統並將其掛載cd到掛載點。文件系統不區分大小寫,Linux 知道這一點。在文件系統中創建一個名為a的文件。像這樣進行實驗:

$ find . . ./a


在這種情況下,該工具必須`a`在某個時候從文件系統中獲取。
* ```
$ find a
a
$ find A
A

這種情況下,該工具使用`a`或`A`取自其命令行參數。文件系統僅確認此類文件存在。文件系統(和作業系統)知道這個特定文件可以稱為`a`或`A`。
```
find a -name A
find A -name a

有!這表明`-name`不關心文件系統對文件的了解。只有`find`事務使用的路徑名。


您的範例中有點類似:`-iname`不關心文件系統對符號連結及其目標的了解。只有`find`事務使用的路徑名。




---


為了澄清和明確說明會發生什麼,讓我們使用以下目錄結構回到您的範例:

. ├── main-file └── sl-file -> main-file


`find . -print`或`find -L . -print`列印:

. ./main-file ./sl-file


這些是路徑名,即用於標識三個*文件的**字元串* (目錄也是一個[文件](https://superuser.com/a/1467109/432690))。字元串來自命令,另外兩個是通過檢查建構的(現在我指的是文件,而不是字元串),了解它是目錄類型,決定我們是否應該下降(一般認為,如果支持),列出其內容:, .`find``.``.``-prune``-maxdepth``main-file``sl-file`


請注意,字元串`/.sl-file`是在對其標識的文件執行任何操作之前建構的。要對文件做任何事情,`find`需要字元串。


但是`-name`或者`-print`不對文件做任何事情,他們不需要它的數據或元數據。它們與路徑名、*字元串*一起工作。


當`-name "*main*"`為任何路徑名評估時,相應的文件或整個文件系統是完全不相關的。唯一相關的是路徑名,它是一個*字元串*;更具體地說,它的最後一個組成部分,即基本名稱,也是一個*字元串*。


對於任何給定的路徑名`-name`,無論您是否使用過`-L`,或者該文件是否首先是符號連結,或者它指向的位置,或者它是否沒有損壞,都無關緊要。它適用於已知的*字元串*。


另一方面,測試喜歡`-type`或`-mtime`需要向文件系統查詢由路徑名標識的*文件。*字元串對他們來說是不夠的。如果是符號連結,`-L`則決定他們是查詢符號連結的目標還是符號連結本身。儘管如此,如果`-print`涉及,那麼無論查詢什麼,它都會列印路徑名。


換句話說:


* 沒有`-L`


  + `./main-file` *字元串*標識`./main-file` *文件*類型`f`
  + `./sl-file` *字元串*標識`./sl-file` *文件*類型`l`
* 和`-L`


  + `./main-file` *字元串*標識`./main-file` *文件*類型`f`
  + `./sl-file` *字元串*還標識類型的`./main-file` *文件*`f`


然後,您應該注意哪些測試或操作適用於路徑名(字元串)以及哪些適用於文件。


`-name`並`-print`使用路徑名,所以`find . -name "*main*"`有或沒有`-L`隻會列印

./main-file


`-type`與文件一起使用,因此`find . -type f`將列印一個路徑名:

./main-file


並將`find -L . -type f`列印兩個路徑名:

./main-file ./sl-file

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