2015-01-25 3 views
1

У меня есть сценарий bash, который запускается во время выпуска программного обеспечения, чтобы проверить, что все исходные файлы включают в себя заголовок лицензии &. Время от времени я должен добавить к нему новое расширение файла, и поэтому моя команда «find» становится немного громоздкой. Я решил немного реорганизовать его, чтобы упростить добавление новых типов файлов. Я хочу сделать это, указав переменную FILEMASKS, которая содержит список масок файлов. Концептуально, это выглядит примерно так:

FILEMASKS="*.?pp *.[ch] *.sh" 
echo FILEMASKS is \'$FILEMASKS\' 

for _fs in $FILEMASKS; do 
    echo \# find . -iname \'$_fs\' # debug 
      find . -iname \'$_fs\' # (not really indented this way) 
done 

Выход выше код не является то, что я ожидал:

FILEMASKS is '*.?pp *.[ch] *.sh' 
# find . -iname '*.?pp' 
# find . -iname '*.[ch]' 
# find . -iname 'check-license.sh' 

В принципе, есть две проблемы:

  1. Только echo линии генерируют любой вывод; фактические вызовы find молчат, указывая, что ничего не найдено, что соответствует. Это озадачивает, так как версия echo'd указывает, что команда find строится именно так, как я ожидаю. (И если я скопирую-вставляю этот вывод эха в оболочку, он возвращает список файлов.)
  2. Цикл for расширяет значения $ _fs, в тех случаях, когда в текущей директории есть файлы, которые соответствуют $ _fs (например, 'check-license.sh', для '* .sh') В то время как мой желаемый результат состоит в том, чтобы все маски файлов в $ FILEMASKS делали его командой find без изменений.

[UPDATE] я только что нашел способ решить # 2 выше: я удаляю *. с начала каждой записи в моей FILEMASKS переменной, а затем добавить его обратно на месте внутри find команда. Таким образом, осталось только # 1. Но меня все еще интересуют другие решения для № 2.

ответ

2

Вы можете использовать массив для вашего списка масок, чтобы обойти эти проблемы.

Что-то вроде этого:

#! /bin/bash 
exts=('*.txt' '*.jpg') 

for ext in "${exts[@]}" ; do 
    echo "* For mask [$ext]:" 
    find . -iname "$ext" 
done 

я получаю этот выход (Каталог верхнего уровня содержит TXT и JPG файл, чтобы убедиться, что не рано подстановка не имеет место):

* For mask [*.txt]: 
./b.txt 
./bar/a.txt 
* For mask [*.jpg]: 
./foo/a.jpg 
./b.jpg 

вашу проблему # 1 это:

$ find . -iname '*.txt' 
./a.txt 
$ find . -iname \'*.txt\' 
$ touch "'b.txt'" 
$ find . -iname \'*.txt\' 
./'b.txt' 

Вы просите find список файлов, которые, буквенные ly, матч '*.?pp', с одинарными кавычками в имени файла. (И так как * и другие глыбовые символы не цитируются, вы получите globbing оболочкой до того, как аргумент будет передан в find.)

+0

Это похоже на работу; Благодарю. Но, можете ли вы объяснить причину №1? –

+0

@ RyanV.Bissell: добавлено «демо» и объяснение. – Mat

+0

Интересно. Я считаю, что я избежал одиночных кавычек для аргумента -iname, потому что я обычно использую одиночные кавычки как таковые, когда выбирая команду 'find' в оболочке ... но внутри этого скрипта я обнаружил, что одинарные кавычки были не позволяя расширять $ _fs. Поэтому я думал, что спуск поможет решить последнюю проблему. Я не понимал, что это заставляет их считаться частью маски имени файла. –

Смежные вопросы