使用可选的括号参数进行查找

使用可选的括号参数进行查找

如何添加可选的分组参数列表来查找?

例如,使用基本参数数组来定义始终可以找到的文件,无论指定什么其他变量条件。

# 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*" )

应用括号中的可选参数以以下形式执行 find:( 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
._.

答案1

[ ! -z $fpterm ] && fANDargs+=( '\(' -ipath "*$fpterm*" '\)' )

你在这里双引号。尝试只使用一层:

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

(此外,您应该在 中使用引号[ ! -z "$fpterm" ]

一般来说,您在数组赋值中使用单词的方式与直接在命令中使用它们的方式完全相同。使用"${array[@]}"引号(就像您所做的那样)将扩展到数组的内容无需进一步修改

(这是人们经常出错的部分,他们似乎期望 shell 处理扩展结果上的引号。事实并非如此,这里更像是一种“正常”编程语言。只要您使用引号来获取摆脱 split+glob 的麻烦。)

当然,这里的背景是它find本身想要看到的只是原样的括号(作为不同的参数)。它不需要看到引号,但需要看到需要它们,因为括号是属于 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'

相关内容