Я пытаюсь создать список параметров в массиве bash
для find
, чтобы найти определенные файлы. Рассмотрим каталог со следующими файлами:
A_foo_0
A_foo_1
A_bar_0
B_foo_0
B_foo_1
B_bar_0
C_foo_0
C_foo_1
C_bar_0
Мой скрипт программно определил, что *foo*
файлы должны быть найдены при поиске, но не файлы, которые начинаются с A
или C
. Таким образом, должны быть найдены только B_foo_0
и B_foo_1
, как показывает следующий ручной вызов find
:
$ find ./ -name "*foo*" ! -name "A*" ! -name "C*"
./B_foo_1
./B_foo_0
Но мне нужно выучить префиксы для динамического исключения, поэтому у меня есть массив, определяющий, какие префиксы следует исключить:
declare -a excludeArray
excludeArray+=(A)
excludeArray+=(C)
Я хочу превратить это в ! -name "A*" and ! -name "C*"
и передать, чтобы найти что-то вроде этого:
excludeOptions=( "${excludeArray[@]/%/\*\"}" ) # Append *" to each element
excludeOptions=("${excludeOptions[@]/#/ ! -name \"}") # Prepend ! -name " to each element
Теперь, если я повторю это, это выглядит довольно хорошо:
echo "${excludeOptions[@]}"
! -name "A*" ! -name "C*"
Но когда я пытаюсь использовать его с find, я получаю следующее:
$ find ./ -name "*foo*" "${excludeOptions[@]}"
find: paths must precede expression: ! -name "A*"
Включение режима отладки показывает, что проблема, вероятно, связана с цитированием элементов:
$ set -x
$ find ./ -name "*foo*" "${excludeOptions[@]}"
+ find ./ -name '*foo*' ' ! -name "A*"' ' ! -name "C*"'
find: paths must precede expression: ! -name "A*"
$ find ./ -name "*foo*" ${excludeOptions[@]}
+ find ./ -name '*foo*' ' ! -name "A*"' ' ! -name "C*"'
find: paths must precede expression: ! -name "A*"
Если я построю массив следующим образом, он будет работать:
$ excludeOptions=( ! -name "A*" ! -name "C*")
$ find ./ -name "*foo*" "${excludeOptions[@]}"
+ find ./ -name '*foo*' '!' -name 'A*' '!' -name 'C*'
./B_foo_1
./B_foo_0
Но я не могу понять, как это сделать динамически.