2017-02-13 9 views
1

Приносим извинения, если это уже ответили, но если это не удается найти правильные условия поиска.Bash: передача шаблона файла в качестве аргумента команды через переменную

Я пытаюсь динамически определять условия поиска (на основе заданных пользователем настроек) для команды найти:

# reading user settings results in array of filename patterns to delete: 
patterns=("*.url" "*.html") 
for i in ${patterns[@]}; do 
    find . -iname $i -delete 
done 

Если я echo команду, результирующая строка выглядит правильно, например,

find . -iname "*.url" -delete 
find . -iname "*.html" -delete 

Я знаю, что мне не хватает чего-то очевидного, но я ничего не пробовал.

Я использую Bash 4.4.5, если это помогает.

---------------- EDIT -----------------

Моя благодарность Чарльз Даффи и л» L'l для правильного решения (решений). Мне было трудно оборачивать голову вокруг цитат в строках массива против цитируемых переменных и не приводить одновременно две переменные.

Извлеченные уроки: всегда указывайте переменные оболочки.

+1

Это проблема, которую http://shellcheck.net/ поймает для вас. –

+0

Я еще не буду отвечать на свой вопрос (если у кого-то есть лучшее решение или объяснение), но я нашел решение. Кажется, двойные кавычки в массиве являются проблемой. Если я разделяю кавычки в массиве и мягкую цитату var '' $ i "', он работает так, как ожидалось. Существует тонкая разница между строкой, которая включает в себя кавычки и строку с кавычками, которую я еще не собираю. –

+2

Извлечение кавычек из определения массива неверно - это приводит к тому, что glob расширяется во время назначения, а не оценивается 'find'. –

ответ

4

The answer by l'L'l является хорошим, но давайте сделаем это немного более эффективным, ссылаясь find только один раз со всеми узорами прошли в одна командная строка:

patterns=("*.url" "*.html") 
find_pat=() 

for i in "${patterns[@]}"; do 
    find_pat+=(-o -name "$i") 
done 

find . -iname '(' "${find_pat[@]:1}" ')' -delete 

При запуске, это будет вызывать:

find . -iname '(' -name '*.url' -o -name '*.html' ')' -delete 

... поэтому, удаляя все файлы, которые соответствуют либо*.url или *.html за один проход.


Примечание:

  • Мы процитировать нашу шарики во все времена: Они указаны на уступки (так мы назначаем сами шарики к patterns массива), на расширение массива (поэтому мы перебираем сами глобы, а не их результаты), а также при расширении в команду find (поэтому мы передаем find синтаксис буквенного шаблона, а не результат расширения этого синтаксиса).
  • Мы добавим -o к массиву find_pat, но затем расширяем его от второго элемента (массивы с индексом 0), тем самым пропуская этот начальный -o. Используемый здесь синтаксис: parameter expansion.
+0

Спасибо за все входные данные и продолжайте обучать меня правильному решению. Я планировал построить конкатенированный шаблон после того, как получил основную форму работы, мне просто тяжело было обернуть голову вокруг строки цитируемого массива против цитируемой переменной. Это и чеканка моего хвоста, пытающегося перестановок «решить» проблему. Спасибо за ваше терпение. –

+1

Рад помочь.Модель исполнения сложна и важна для понимания - чтобы дать вам обзор на высоком уровне, который должен дать вам несколько ключевых слов для поиска, нецитированные расширения претерпевают разделение строк и глобусы (но * не * другие этапы синтаксического анализа, такие как цитата поэтому вы не можете просто запустить '$ cmd' для запуска произвольной команды, хранящейся в этой переменной, - см. [BashFAQ # 50] (http://mywiki.wooledge.org/BashFAQ/050) в этом пункте) , Вы можете начать с [BashParser] (http://mywiki.wooledge.org/BashParser) и его различных ссылок. –

3

Вы должны дважды процитировать переменные:

for i in "${patterns[@]}"; do 
    find . -iname "$i" -delete 
... 

Это предотвратит универсализации и разбиение слов.

Вы всегда можете проверить скрипт на https://www.shellcheck.net/ ошибок, а также ...

+0

Спасибо за решение. Я даже не процитировал одновременно переменную массива и цикла в своем предыдущем тестировании. Который [https://www.shellcheck.net/] (https://www.shellcheck.net/) отметил. –