Bash

使用可選的帶括號的參數查找

  • March 27, 2022

如何添加可選的分組參數列表來查找?

例如,使用一組基本參數來定義將始終找到的文件,而不管指定了哪些其他變數條件。

# args to find any files ending _count or _scan

._. fargs=( -type f -name '*_count' -o -name '*_scan' )
._. cd /sys/fs/ext4/sda1
._. find . \( "${fargs[@]}" \) 2> /dev/null
./mb_min_to_scan
./errors_count
./mb_max_to_scan
./msg_count
./warning_count

添加可選的附加參數

._. fpterm=warning
._. fpterm2=max
._. fANDargs=( -ipath "*$fpterm*" -o -ipath "*$fpterm2*" )

應用括號中的可選參數以使用以下形式執行查找:( a 或 b 或 c )和( d 或 e 或 f )

._. find . \( "${fargs[@]}" \) \( "${fANDargs[@]}" \) 2> /dev/null
./dm-1/mb_max_to_scan
./dm-1/warning_count
./dm-0/mb_max_to_scan
./dm-0/warning_count
./sda1/mb_max_to_scan
./sda1/warning_count

但是當可選的 arg 數組為空時,它會停止滿足其他條件,並且根本找不到文件:

._. fANDargs=()
._. find . \( "${fargs[@]}" \) \( "${fANDargs[@]}" \) 2> /dev/null
._. 

空括號導致問題:

._. find . \( "${fargs[@]}" \) \( \) 2> /dev/null
._.

而通常,一個空的 arg 數組不會阻止滿足其他條件:

._. fANDargs=()   
._. echo "${fANDargs[@]}"

._. find . \( "${fargs[@]}" \) "${fANDargs[@]}" 2> /dev/null
...
./sda1/mb_min_to_scan
./sda1/errors_count
./sda1/mb_max_to_scan
./sda1/msg_count
./sda1/warning_count

因此,如果僅當可選 args 數組不為空時才可以添加方括號,則該命令可能會起作用。

但是如何有條件地添加括號呢?

將括號添加到數組時似乎不起作用,例如:

._. fpterm=warning
._. fANDargs=()
._. [ ! -z $fpterm ] && fANDargs+=( '\(' -ipath "*$fpterm*" '\)' )
._. echo "${fANDargs[@]}"
\( -ipath *warning* \)
._. find . \( "${fargs[@]}" \) "${fANDargs[@]}" 2> /dev/null
._.
[ ! -z $fpterm ] && fANDargs+=( '\(' -ipath "*$fpterm*" '\)' )

你在這裡雙引號。嘗試僅一層:

fANDargs+=( \(  -ipath "*$fpterm*" \)  )   # or  
fANDargs+=( '(' -ipath "*$fpterm*" ')' )   # or with "(" and ")"

(你也應該在 中使用引號[ ! -z "$fpterm" ]

通常,您在數組賦值中使用單詞的方式與在命令中直接使用它們的方式完全相同。與引號一起使用"${array[@]}"(如您所做的那樣)將擴展為數組的內容而無需進一步修改

(這是人們似乎經常出錯的部分,他們似乎期望 shell 處理擴展結果的引號。事實並非如此,它更像是這裡的“普通”程式語言。前提是您使用引號來獲取擺脫分裂+球的滋擾。)

當然,這裡的背景是,find它本身想要看到的只是原樣的括號(作為不同的參數)。它不需要看到引號,但shell需要它們,因為括號是特殊字元,是 shell 語法的一部分。所以你可以somecmd { foo bar }不帶引號使用,但你確實需要在somecmd \( foo bar \).


順便說一句,GNU find 警告一組空括號:

$ find . \( \)
find: invalid expression; empty parentheses are not allowed.

而且,好吧,從邏輯上講,無論如何這似乎很奇怪。我的第一直覺是說空括號必須評估為虛假,這將find \( whatever \) \( \)永遠不匹配。但它也可以被解釋為真實的,這似乎是 Busybox 所做busybox find . \( \) -name '*.txt'的,與busybox find . -name '*.txt'.

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