Linux

從 bash 路徑數組中提取缺失的路徑

  • April 20, 2020

我有一組路徑:

paths=(
 /foo/exists1
 /foo/exists2
 /foo/missing1
)

要找到那些失去的:

ls "${paths[@]}" 1>/dev/null

顯示:

ls: 無法訪問’/foo/missing1’: 沒有這樣的文件或目錄

好的。現在我想清理它:

ls "${paths[@]}" 1>/dev/null | sed 's/ls: cannot access //' | sed 's/: No such file or directory//''

但我得到:

ls: 無法訪問 ‘/foo/missing1’: 沒有這樣的文件或目錄

/foo/exists1

/foo/exists2

所以sed不起作用,並且現有文件也會顯示。

為什麼會發生這種情況(為什麼會忽略1>/dev/null),我該如何解決?

已經發現了您的程式碼沒有按照您的預期執行的直接原因:錯誤ls被報告給 stderr(如POSIX 所建議的那樣),該錯誤未被管道擷取為輸入。因此,您得到了正常輸出(通過您的sed語句未更改通過)和 stderr(繞過它們)的混合。我不知道為什麼您的ls輸出在兩次通話之間發生了變化;將標準輸出重定向到 /dev/null 應該具有從輸出中刪除所有“正常”(現有路徑)的效果。不過,解決此問題的方法不是將 stderr 推入 stdout。

ls如果您想要一個可靠的腳本,那麼對輸出進行後處理是一個危險的想法。關於該主題的一篇好文章是“為什麼不應該解析 ls(1) 的輸出”,可在 woodedge.org 站點上找到。Unix 和 Linux 網站上的一個深入 Q/A 涉及一些問題:為什麼解析ls(以及要做什麼)?. 結果是 UNIX 文件名可以包含幾乎任何字元,包括空格、製表符、換行符、單引號、雙引號、轉義單引號等!對於一些簡單的例子,考慮這些名稱的目錄,所有這些都是完全合法的:

  • “沒有這樣的文件” ( mkdir "No such file")
  • “ls: 無法訪問 ‘foo’: 沒有這樣的文件或目錄” ( mkdir "ls: cannot access 'foo': No such file or directory")
  • “目錄

嵌入式

換行符” ( mkdir $'directory\nwith\nembedded\newlines')

第一個是被grep. 第二個也被錯誤地擷取,但隨後進一步被破壞成一條完全不同的路徑——可能存在也可能不存在!——通過sed陳述。第三個是當你將輸出傳遞給ls面向行的程序時發生的一個例子;如果該目錄不存在,ls將在不止一行上這樣說,這可能就是您最終得到兩個單獨sed語句的方式!

為了區分“好路徑”(存在且可讀的路徑)和“壞路徑”,我建議循環遍歷數組並為每個數組建構新數組。

for p in "${paths[@]}"
do
 if [ -r "$p" ]
 then
   goodpaths+=("$p")
 else
   badpaths+=("$p")
 fi
done

然後你可以對每組做任何你喜歡的事情:

printf 'Good path: -->%s<--\n' "${goodpaths[@]}"
echo
printf 'Bad path: -->%s<--\n' "${badpaths[@]}"

引用自:https://serverfault.com/questions/1013008