Bash

管道查找到 xargs 時,無法修改位於不同位置的同名文件

  • July 14, 2020

在 Mac 上使用 gnu 工具

我不確定發生了什麼,但似乎將 find 的輸出通過管道傳輸到 xargs 在觸摸出現在不同位置的目錄結構中的同名文件時存在一些問題

我的目錄:

dir
-- dirone
---- myfile.txt
---- otherfile.txt
-- dirtwo
---- myfile.txt

當我執行此命令時,出現權限被拒絕錯誤:

find dir -name "myfile.txt" | xargs -0 -I FILE sh -c "ls FILE"

我什至不能觸摸/ls文件。如果我訪問其中有一個的“otherfile.txt”,我看不到任何問題

find dir -name "otherfile.txt" | xargs -0 -I FILE sh -c "ls FILE"

是否有某種競爭條件或什麼?我最終想修改文件,sed -i但我什至不能。我不明白,因為完整的文件路徑正在傳遞給 xargs 所以它應該有完整的路徑,這使得它的同名無關緊要嗎?

編輯:好的,仍然不明白為什麼我會收到燙髮錯誤,但這似乎有效:

find dir -name "otherfile.txt" -type file -print0 | xargs -0 -I FILE sh -c "ls FILE"

只是刪除-0也有效,我不確定哪種方式更好/更安全?

鑑於您的目錄設置:

$ find dir
dir
dir/dirtwo
dir/dirtwo/myfile.txt
dir/dirone
dir/dirone/myfile.txt
dir/dirone/otherfile.txt

如果我使用您的(原始)命令,那麼我可以重現您的原始問題:

$ find dir -name "myfile.txt" | xargs -0 -I FILE sh -c "ls FILE"
dir/dirtwo/myfile.txt
sh: line 1: dir/dirone/myfile.txt: Permission denied
$

為了更好地理解發生了什麼,讓我們嘗試該命令的變體:

$ find dir -name "myfile.txt" | xargs -0 -I FILE echo -FILE-
-dir/dirtwo/myfile.txt
dir/dirone/myfile.txt
-

請注意, FILE 擴展為單個標記:dir/dirtwo/myfile.txt\ndir/dirone/myfile.txt\n. 為什麼?因為您告訴xargs令牌是 NUL 分隔的(使用-0開關),並且兩個文件名之間沒有 NUL 字元。

有了這個,如果我們回到你原來的命令:... | xargs -0 -I FILE sh -c "ls FILE",那變成:

ls dir/dirtwo/myfile.txt
dir/dirone/myfile.txt

所以它列出了一個,並嘗試執行第二個。這就是你得到“權限被拒絕”的原因——第二個文件不可執行。

如您所見,添加-print0選項find將解決問題。使用該選項,find將在標記之間放置一個 NUL 字元 -xargs使用該-0選項時期望的相同字元。類似地,只需-0關閉選項即可xargs解決問題,因為預設情況下兩者都find使用xargs空格作為分隔符。

-print0and選項對於文件名可以包含空格的-0情況很有用(這會破壞將空格視為標記分隔符的預設行為)。

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