Linux

無法在查找結果的 -exec 命令中為數組賦值

  • September 24, 2019

我編寫了以下命令以將查找結果分配到數組中,以刪除超過 7 天的文件。

F_ARR[0]=''
unset F_ARR
find "$CDIR" ! -type d -mtime +7 -exec sh -c '
   for pathname; do
       F_ARR+=("$pathname")
   done' sh {} +
echo ${#F_ARR[@]}

但是,當我列印數組 F_ARR 的長度時,它顯示為 0。我是否在程式碼中犯了錯誤?

find ... -exec sh -c 'sh code' {} +

從您的 bash/ksh shell 中,在執行一個或多個命令呼叫find的新程序中執行命令。shsh code只能影響sh解釋該程式碼的呼叫變數(順便說一句,sh並不意味著支持數組)。

如果要將找到的文件的路徑儲存find到目前 shell 的數組中,則必須由該 shell 執行分配。

使用bash4.4+,你可以這樣做:

readarray -td '' F_ARR < <(find "$CDIR" ! -type d -mtime +7 -print0)

如果您find不支持-print0,您可以將其替換為-exec printf '%s\0' {} +

(對於舊版本bash,請參閱此類似問題的答案中如何做到這一點)。

在這裡,您也可以改用zshshell 並執行以下操作:

f_arr=($CDIR/**/*(NDm+7^/))

與上述的不同之處在於:

  • 文件列表已排序,您可以添加oNglob 限定符以禁用排序
  • $CDIR即使超過 8 天,它本身也不會被包括在內。
  • if$CDIR是指向目錄的符號連結,zsh仍會進入該目錄。

由於您同時使用 和 標記您的問題bashksh請注意,ksh 有不同的實現和變體(ksh88、ksh93、即將推出的 ksh2020 (最初)由 David Korn、pdksh 及其衍生產品如OpenBSDshmksh可以添加zsh的ksh仿真模式)。

大多數bash功能確實來自ksh88and ksh93,少數來自zshand mkshreadarray是為數不多的原生bash且在其他地方找不到的功能之一。

ksh93 確實在 1993 年添加了一個-d選項read,後來被 bash (2000) zsh (2003) 和 mksh (2011) 複製,但只有 bash、zsh、mksh 和 ksh2020 可以將它與空分隔符一起使用來處理 NUL 分隔的記錄。在 ksh86 (1986) 中添加了程序替換,但沒有一個基於 pdksh 的 ksh 變體支持它,所以上面提到的舊版本的方法bash在任何版本的 ksh 中都不起作用(除了 zsh 的 ksh 仿真模式)。

在基於 ksh88、ksh93 和 pdksh 的 shell 中,一種選擇是對 的輸出進行後處理,find以便生成可以定義該數組並評估該程式碼的 shell 程式碼eval

eval set -A F_ARR "$(
 LC_ALL=C find "$CDIR" ! -type d -exec awk -v q="'" -- '
   BEGIN {
     for (i = 1; i < ARGC; i++) {
       gsub(q, q "\\" q q, ARGV[i])
       printf " %s", q ARGV[i] q
     }
     exit
   }' {} +
)"

(這裡假設$CDIR不以+or開頭-。如果可能,通過某些ksh實現,您可以使用set -A F_ARR --。無論如何,如果它以 開頭-find將會窒息)。

同樣的方法可以通過替換用於任何 POSIX sh set -A F_ARRset --然後填充一個 POSIX shell 數組:"$@".

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