無法在查找結果的 -exec 命令中為數組賦值
我編寫了以下命令以將查找結果分配到數組中,以刪除超過 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
的新程序中執行命令。sh
將sh code
只能影響sh
解釋該程式碼的呼叫變數(順便說一句,sh
並不意味著支持數組)。如果要將找到的文件的路徑儲存
find
到目前 shell 的數組中,則必須由該 shell 執行分配。使用
bash
4.4+,你可以這樣做:readarray -td '' F_ARR < <(find "$CDIR" ! -type d -mtime +7 -print0)
如果您
find
不支持-print0
,您可以將其替換為-exec printf '%s\0' {} +
。(對於舊版本
bash
,請參閱此類似問題的答案中如何做到這一點)。在這裡,您也可以改用
zsh
shell 並執行以下操作:f_arr=($CDIR/**/*(NDm+7^/))
與上述的不同之處在於:
- 文件列表已排序,您可以添加
oN
glob 限定符以禁用排序$CDIR
即使超過 8 天,它本身也不會被包括在內。- if
$CDIR
是指向目錄的符號連結,zsh
仍會進入該目錄。由於您同時使用 和 標記您的問題
bash
,ksh
請注意,ksh 有不同的實現和變體(ksh88、ksh93、即將推出的 ksh2020 (最初)由 David Korn、pdksh 及其衍生產品如OpenBSDsh
或mksh
可以添加zsh的ksh仿真模式)。大多數
bash
功能確實來自ksh88
andksh93
,少數來自zsh
andmksh
。readarray
是為數不多的原生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_ARR
,set --
然後填充一個 POSIX shell 數組:"$@"
.