Bash

在查找時執行查找

  • November 3, 2020

我對“linux run find on find”進行了網路搜尋,但沒有產生相關結果。我想通過 find 建構文件列表,然後在該列表上再次執行 find 。

在修復了一些“愚蠢”的錯誤之後,我猜想來自對命令行工作的很少經驗,最終命令是:

find "path1" -size 0 -printf "%f\0" | xargs -0 --max-args=1 --verbose find "path2" -exec ls -l {} \\\; -name

作為--verbose,我看到命令執行為

find path -exec ls -l {} \; -name foundfilename

和輸出missing argument to exec

如果我直接執行生成的命令建構xargs(由於某種原因添加雙引號 xargs –verbose 輸出未命中,但顯然在實踐中使用 find 沒有包含空格的路徑問題:

find "path" -exec ls -l {} \; -name foundfilename

並且輸出看起來像path.

  1. find為什麼 xargs 和直接執行的結果不同?
  2. 貌似-exec不能先行-name,對嗎?
  3. 最後一點:如何find在另一個結果上正確執行find

系統:Linux Mint 19.2

在評論後添加以澄清第二個問題:

如果我跑

find "path" -name foundfilename -exec ls -l {} \;

我得到了ls按預期找到並列出的幾個文件的輸出,即第二個問題。

我對兩個名為12的文件進行了測試設置/media/ramdrive

marina@tpx:~$ find /media/ramdrive -exec ls {} \; -name 1
1  2
/media/ramdrive/2
/media/ramdrive/1
marina@tpx:~$ find /media/ramdrive -name 1 -exec ls {} \;
/media/ramdrive/1

找人:

-執行命令;執行命令;如果返回 0 狀態,則為 true。所有以下要查找的參數都被視為命令的參數,直到由;' is encountered. The string {}’ 組成的參數被目前文件名替換為正在處理的目前文件名,它出現在命令的參數中,而不僅僅是在單獨的參數中,如在某些版本的 find 中。這兩種結構都可能需要轉義(使用 `’)或引用以保護它們不被 shell 擴展。有關使用 -exec 選項的範例,請參見範例部分。指定的命令對每個匹配的文件執行一次。該命令在起始目錄中執行。使用 -exec 操作存在不可避免的安全問題;您應該改用 -execdir 選項。

我不明白為什麼-exec不能在匹配選項之前。

實際上我不明白“它出現在命令的參數中的所有地方,而不僅僅是在它單獨存在的參數中”的含義。

添加兩個:

我雖​​然通過以下方式找到了解決方案:

find "path1" -size 0 -printf "%f\0" | xargs -0 --max-args=1 --verbose find "path2" -name | xargs ls -l

但是 find 的預設列印不引用結果,因此帶有空格的路徑失敗。如果有實用程序來添加引號?

xargs為什麼與直接find執行的結果不同?

當你輸入 find path -exec ls -l {} \; -name foundfilename一個 shell 時,shell 讀\;作“傳遞;給命令”。如果它只是;鍵入,它將是一個命令分隔符。反斜杠被外殼“吃掉”並改變其關於;.

xargs說它執行 find path -exec ls -l {} \; -name foundfilename時,它實際上傳遞\;給命令(即 to find),沒有外殼可以去除反斜杠。所以\;這裡是錯誤的:-exec期望;or +,它都沒有得到,因此“缺少 exec 的參數”。


貌似-exec不能先行-name,對嗎?

不正確。它可以。也許不應該,這取決於你想做什麼。您的兩個命令的不同結果可以很容易地解釋。這兩個命令是:

find /media/ramdrive -exec ls {} \; -name 1
find /media/ramdrive -name 1 -exec ls {} \;

關鍵事實:

  • -exec也是一種考驗。如果內部命令返回,則它成功0
  • 測試由運算符連接:(-o邏輯或)或-a(邏輯與)。-a假設缺少運算符(例如您的情況) 。
  • 使用-test1 -o -test2or -test1 -a -test2-test1首先測試。如果結果僅由-test1then確定,則-test2不會執行。特別是當且僅當成功時,此方法-test1 -a -test2才會執行(如果失敗則不需要,因為我們已經知道結果:失敗)。test2``-test1``-test2

如果您的整體測試是-exec ls {} \; -name 1(即-exec ls {} \; -a -name 1),則-exec對每個候選人進行。這已經在標準輸出上列印了一些東西。對於每個候選人都ls成功了,所以執行另一個測試;但這沒關係,因為其他測試不列印任何內容並且沒有進一步的測試/操作(預設值-print被 previous 抑制-exec)。

如果您的整體測試是-name 1 -exec ls {} \;(即-name 1 -a -exec ls {} \;),則-name對每個候選人進行。測試不列印任何內容,但它的結果決定是否-exec執行。所以ls執行 iff-name成功,它列印一些東西 iff-name成功。


如何find在另一個結果上正確執行find

可以find-exec另一個內部執行find。例如,這會在名為 的目錄中找到所有符號連結lib

find / -type d -name lib -exec find {} -type l \;

您可以從/lib/,/var/lib/等獲得結果/usr/lib/

有幾個問題:

  • 這從外部執行一個內部find每個結果find。如果您想find一次使用一個的所有結果,即使用一個other,情況就不同了find
  • 如果內部find也需要執行-exec,則沒有直接的方法可以傳遞{}, ;(鍵入為\;)或+傳遞給它,因為這些將由外部解釋find。一種解決方案是使用xargs(並且您確實使用了),它通常需要非 POSIX 選項以使其對於包含換行符的名稱不會失敗。find另一種解決方案是在兩個s之間生成一個外殼(就像我在撰寫我的時出現的另一個答案一樣,我不會重複它的解決方案)。

我不明白“它出現在命令的參數中的所有地方,而不僅僅是出現在它單獨的參數中”的含義。

POSIX需要單獨find擴展。對於像或“它是實現定義是否替換這兩個字元或使用字元串而不更改”這樣的參數。您的版本將替換為or之類的參數,並且手冊明確說明了這一點。 {}``{}.txt``foo{}bar``find``find``{}``{}.txt``foo{}bar

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