Zsh использует массив в команде поиска

Я столкнулся с той же проблемой. Для меня работает добавление опцииvers=2.0

4
24.05.2021, 13:34
2 ответа

Да, здесь вам нужно сгенерировать 3 аргумента для findдля каждого элемента вашего массива. Также find's -nameпринимает шаблон, поэтому, чтобы он соответствовал точным именам файлов, вам нужно экранировать операторы подстановочных знаков find(*, ?, [и \):

.
set -o extendedglob # for (#m)
exclusions=()
for name ($drivers) exclusions+=(! -name ${name//(#m)[?*[\\]/\\$MATCH})

find ${refind_efi_dir}drivers_x64/ $exclusions -type f -exec rm -f {} +

"${array[@]/pattern/replacement}"расширяется до такого количества элементов, которое есть в массиве, после подстановки, выполненной для каждого из них.

Здесь, учитывая, что -nameпринимает шаблон имени файла , он не должен содержать /, поэтому вы можете заменить каждый элемент на !/-name/element, а затем разделить на/:

set -o extendedglob # for (#m)
find ${refind_efi_dir}drivers_x64/ \
  ${(@s[/])${drivers//(#m)[?*[\\]/\\$MATCH}/#/!\/-name\/} \
  -type f -exec rm -f {} +

Или используйте $'\0'вместо /, так как его нельзя передать в качестве аргумента внешней команде:

set -o extendedglob # for (#m)
find ${refind_efi_dir}drivers_x64/ \
  ${(@0)${drivers//(#m)[?*[\\]/\\$MATCH}/#/!$'\0'-name$'\0'} \
  -type f -exec rm -f {} +

Но разборчивости это не сильно способствует...

Здесь вы также можете использовать zshglob для всего:

(cd -P -- $refind_efi_dir && rm -f -- **/^(${(~j[|])drivers})(D.))

Если флаг расширения параметра j[|]объединяет элементы массива $driversс |и ~, это приводит к тому, что |рассматривается как оператор глобуса. Этот шаблон инвертируется с помощью ^(, для которого вам нужна опция extendedglob). Dдля включения скрытых файлов, .для ограничения обычными файлами, такими как ваш -type f.

6
28.07.2021, 11:29

"${drivers[@]/#/! -name }"помещает ! -name в то же слово оболочки, что и каждый элемент массива. "${=drivers[@]/#/! -name }"разделит результаты, так что !и -nameокажутся отдельными словами оболочки, но элементы массива также будут разделены пробелами.

Одним из решений является злоупотребление квалификаторами eиPglob:

find … /(e\''reply=($drivers)'\'P\''!'\'P\''-name'\') …

/(…)расширяет шаблон glob /, который всегда соответствует ровно одному (корневому каталогу ), и применяет к нему квалификаторы glob. Квалификатор glob eзаменяет каждое совпадение новым значением переменной-массива reply, которую мы устанавливаем в список слов, к которым мы хотим применить последующие квалификаторы glob. Затем квалификатор glob P,используется дважды, вставляет указанный текст как отдельные слова перед каждым совпадением.

В этом конкретном случае , как показал Стефан Шазела , вы можете просто делать все с помощью zsh globs, не используя find.

2
28.07.2021, 11:29

Теги

Похожие вопросы