2012-01-26 2 views
1

У меня есть сценарий bash, который я хочу взять с некоторыми необязательными аргументами ввода, за которым следует либо имя файла, либо спецификация файла, содержащая подстановочные знаки.Как использовать подстановочный знак с getopts в сценарии bash?

Если я бегу getopts_problem.sh -td *.txt сценарий благополучно выводит список файлов .txt в текущем каталоге:

файл является readme.txt letter_to_editor.txt someotherfile.txt

Если я пробег getopts_problem.sh -td *.ABC выходы сценария

файл * .ABC

В текущем каталоге нет файлов с расширением ".ABC". По какой-то причине сценарий интерпретирует «* .ABC» как имя файла. Как я могу заставить скрипт распознавать «* .ABC» в качестве расширения имени файла, а не фактическое имя файла? Код выглядит следующим образом:

# !/bin/sh 
doDry=0 
doTimestamp=0 

while getopts ":dt" OPT; 
do 
    case $OPT in 
     d) doDry=1 ;; 
     t) doTimestamp=1 ;; 
     ?) echo 'Bad options used. ' 
      exit 1 ;; 
    esac 
done 

shift $(($OPTIND - 1)) 
[email protected] 

for file in "$fileList" 
do 
    echo file is $file 
done 

exit 0 
+0

Возможный дубликат [Управление расширением подстановок командной строки оболочки на C или C++] (http://stackoverflow.com/questions/2617453/controlling-shell-command-line-wildcard-expansion-in-c-or-c) – Matt

ответ

2

подстановочные шаблоны расширены bash перед выполнением вашего сценария. Не оболочка, которая интерпретирует скрипт, а ту, с которой вы ее запускаете. И независимо от того, сохраняет ли он шаблон, ничего не пропускает или не работает, зависит от nullglob, failglob и некоторых таких опций (см. man bash).

Кроме того, в for file in "$fileList" цитаты явно указывают оболочке не, чтобы развернуть переменную.

+0

Семантический приговор: двойные кавычки допускают переменное расширение (т. Е. Заменяют его имя на его значение), но предотвращают разбиение слов (т. Е. Разбивая его на несколько слов на основе пробелов). Чистый результат: цикл выполняется ровно один раз, а '$ file' установлен на весь список файлов. Решение состоит в использовании массивов: 'fileList = (" $ @ "); для файла в "$ {fileList [@]}"; ... '- это правильно разбивает список файлов, даже если некоторые имена файлов содержат пробелы или другие« забавные »символы. –

+0

Вы правы насчет котировок вокруг $ fileList. Я вынул их, и теперь выходят три строки «file», перечисляя каждый .txt-файл отдельно. Но он все еще считает, что «* .ABC» - это имя файла, что является проблемой. Обходной путь, который я придумал, заключается в использовании '[-e $ file]' в теле кода, чтобы проверить, существует ли файл. Я не знаю, является ли это приемлемым способом или это гигантский клоч, но он действительно работает. – Kevin

+0

@ Kevin, как я уже сказал, расширение подстановочных знаков, которые не соответствуют файлам, контролируется nullglob, ищите его в man-странице bash. И также имейте в виду, что, если вы не процитируете его, он будет обрабатываться оболочкой, которую вы используете для запуска скрипта. Запомни. –