Почему nullglob влияет на завершение вкладок?

После shopt -s nullglob , как я заметил, что shopt -s nullglob завершено полностью перестало работать. Почему это так? extglob по-видимому, доброкачественный , что еще может повлиять на nullglob?

Наблюдается:

  • Ubuntu 14.04 (bash 4.3.11(1)-release )
  • Arch Linux (bash 4.3.42(1)-release )

В отличие от extglob , nullglob делает огромную разницу в поведении оболочки. Это означает, что слово, содержащее подстановочные знаки, которые, вероятно, не соответствуют ничему, приводит к исчезновению слова вместо сохранения.

В большинстве случаев код, который прерывается с помощью nullglob , также будет прерываться без него, если определенный каталог содержит файлы, которые совпадают с некотируемым шаблоном. В зависимости от шаблона существование таких файлов может быть более или менее вероятным (и может быть невозможно, если скрипты контролируют, какие имена файлов присутствуют, например, потому что он переключается во временный каталог, который он заполняет).

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

Глядя на то, что происходит при завершении аргумента ls с set -x , я вижу, что вывод с nullglob и без nullglob начинается с

 + [[ 0 -gt 0 ]] + ref='words[0]' + eval 'words[0]=${!ref}${COMP_WORDS[i]}' ++ words[0]=ls + line=' ' 

(рабочий) против

 + [[ 0 -gt 0 ]] + ref='words[0]' + eval + line=' ' 

с nullglob. Видите эту линию eval ? Это признак того, что аргумент был похож на шаблон glob. Соответствующий код находится в функции __reassemble_comp_words_by_ref :

  # Append word separator to current or new word ref="$2[$j]" eval $2[$j]=\${!ref}\${COMP_WORDS[i]} 

[ является подстановочным знаком, поэтому $2[$j]=\${!ref}\${COMP_WORDS[i]} является шаблоном подстановочных знаков, а с помощью nullglob он исключается, поскольку он ничего не соответствует. Это также ломается даже без nullglob если текущий каталог содержит файл с именем words0=${!ref}${COMP_WORDSi} – это довольно экзотично, но это может произойти.

Исправление состоит в том, чтобы добавить отсутствующие двойные кавычки:

  eval "$2[$j]=\${!ref}\${COMP_WORDS[i]}" 

Возможно, есть и другие части этого скрипта, которые нуждаются в подобных исправлениях, я еще не исследовал их.

Это ошибка в bash_completion (не в bash). Об этом сообщается в 2012 году, и исправление находится в дорожной карте для версии 3.0.