Як додати шаблон для завершення bash (для розпакування)?


12

Коли я набираю

unzip <tab>

Я отримую список усіх файлів, що закінчуються .zip, що є стандартною поведінкою заповнення вкладки для unzipкоманди.

Однак я також хочу завершити bash для unzipсписку файлів, які закінчуються .udp, окрім .zipфайлів. Як я можу досягти такої поведінки у своїх місцевих .bashrc?

Відповіді:


23

Замість того, щоб продовжувати коментувати…


complete -f -X '!*.@(zip|udp)' unzip

має додати завершення для

-f -X '!*.@(zip|udp)'
 |  |  | |||________|
 |  |  | ||     |
 |  |  | ||     +- filterpat: zip or udp
 |  |  | |+-------------  @ : Matches one of the given patterns
 |  |  | +-------------- *. : Anything+<dot>
 |  |  +----------------  ! : Negate
 |  +------------------- -X : Filter out matches in "filterpat"
 +---------------------- -f : files

Іншими словами: заповніть файли та видаліть усі, що не закінчуються на .zipабо .udp.


Екстри

Якщо ви додасте -o defaultзавершення, буде завершено / відповідати всі файли та каталоги, якщо файли не закінчуються на .zipабо .udp.

Якщо ви додасте -o plusdirsзавершення, ви додасте будь-які каталоги на додаток до будь-яких збігів файлів, що закінчуються на .zipабо .udp.

Поточний

При використанні complete -p unzipви отримуєте поточну схему.

З ваших коментарів це звучить здебільшого так, як вам не вистачає +або @в шаблоні, як у:

# Err:
complete -f -X '!*.(zip|udp)' unzip
                   |
                   +---- Missing + or @

що означало б відповідати будь-якому файлу, який буквально закінчується.(zip|udp) . Напр

touch 'file_test.(zip|udp)'

Подивіться також цей розділ посібника:

можливо, наприклад extglob, не включено. Увімкнути:

shopt -s extglob

Перевірте поточний стан усіх shoptналаштувань, ввівши:

shopt

Функція

Якщо це так, -F somethingце означає, що він використовує функцію, названу чимось, для створення списку завершень.

_filedir_xspec, Як правило , є функцією Debian. У вас може бути щось подібне:

$ cat /etc/bash_completion
. /usr/share/bash-completion/bash_completion

Що означає /usr/share/bash-completion/bash_completionотримати джерело. Тут ви знайдете відповідну функцію . Кілька рядків далі ви бачите, що ця функція / завершення додається функцією, названою _install_xspecнаприклад:

_install_xspec '!*.@(zip|[ejsw]ar|exe|pk3|wsz|zargo|xpi|s[tx][cdiw]|sx[gm]|o[dt][tspgfc]|od[bm]|oxt|epub|apk|do[ct][xm]|p[op]t[mx]|xl[st][xm])' unzip zipinfo

Ручні записи:


Оновити до коментарів 1:

- Не збігається через недійсні архіви чи дозволи на файли.

Це не повинно впливати на результат. completeвідповідає лише файлам, заданим правилами, і не обробляє файли. Якщо ви можете перерахувати їх ls, вони повинні відповідати.

В якості бічної примітки можна додати таку функціональність, використовуючи повну функцію:

function _unzip_validated() {
    # 1. Generate list of files ending in e.g. .zip and .udp
    # 2. Validate each file and remove invalid ones from file list.
}

complete -F _unzip_validated unzip

- Кольори. Чому lsвідрізнити test.zipвід test.upd?

Це не впливає complete. Кольори lsнадає компанія $LS_COLORS. Спробуйте:

echo "$LS_COLORS" | tr : '\n' | sort

Ви повинні побачити щось таке, *.zip=01;31що означає:

*.zip=01;31
|____| |  |
   |   |  +--- Red
   |   +------ Bold
   +---------- Files with .zip extension

*.udp з іншого боку, немає жодного запису, пов'язаного з ним, тому немає забарвлення.


Наступний крок (повинен був бути першим)

  1. Відкрийте термінал і перейдіть до каталогу з тестовими файлами. І .zip, і .udp
  2. Введіть bash --norc
  3. Введіть complete -f -X '!*.@(zip|udp)' unzip
  4. Введіть shopt -s extglob
  5. Введіть unzip <tab><tab>

Результат?

Також натисніть кнопку " Змінити" під своїм запитанням та додайте вихід:

bind -V
shopt
env

може бути корисним.


Дуже дякую за ваше відмінне та тривале пояснення, але все одно це не працює. complete -p unzipвиходить complete -f -X '!*.@(zip|udp)' unzipі unzip <tab>завершує файл з назвою test.zip. Однак у каталозі також є файл, названий test.updтаким чином, який не знайдено після заповнення вкладки unzip. Чи може пояснити факт дозволу на файл чи нульову довжину файлу цю дивну поведінку?
Олексій

@Alex: Потрібно отримати завершення як на порожніх, так і на дійсних файлах, а також на файлах, на які немає дозволу. Це та ж поведінка, якщо ви додасте його до тестового сценарію? Наприклад, 1. тестовий сценарій із набором виконання:, ~/bin/testing2. complete -f -X '!*.@(zip|udp)' testing, 3. testing <tab><tab>?
Руніум

@Alex: Ви також можете оновити Q з виходом shopt
Runium,

extglobактивовано. Приклад із "тестуванням" вибирає zipфайл лише знову. Я помічаю, що test.zipвідображається в червоному кольорі, в той час як test.updвін відображається в білому кольорі з ls -l, обидва файли порожні з однаковими дозволами, зміни власника та об'єднання груп. Чому lsвідрізнити test.zipвід test.upd? Можливо, це натяк на проблему, яку я маю?
Олексій

@Alex: додано оновлення.
Руніум

3

У файлі /etc/bash_completion, який ви, мабуть, десь шукаєте, завершення за замовчуванням, принаймні для моєї версії bash(v4.2.25):

complete -f -X '!*.@(zip|[ejw]ar|exe|pk3|wsz|zargo|xpi|sxw|o[tx]t|od[fgpst]|epub|apk)' unzip zipinfo

Спробуйте змінити весь вираз на

complete -f -X '!*.@(zip|[ejw]ar|exe|pk3|wsz|zargo|xpi|sxw|o[tx]t|od[fgpst]|epub|apk|udp)' unzip zipinfo

І додайте до свого .bash_profile


Це не вирішує мою проблему. Якщо я це роблю і джерело його, unzip <tab>ні знахідки, .zipні .updфайли, ні інші файли.
Олексій

Спробуйте двічі натиснути вкладку, перевірте, чи це інакше. Чи працюють інші доповнення, як очікувалося? Наприклад, gzipз .gzфайлами?
bsd

Натискання вкладки двічі нічого не змінює. Використання gunzipз .gzфайлами виберіть тільки ті файли , що закінчуються на .gz, але це визначення також різні: complete -F _filedir_xspec gunzip.
Олексій

Ви джерело файлу /etc/bash_completionу вашому .bashrc?
bsd

Спробуйтеshopt -s extglob
Едвард Фолк

2

Спробуйте додати цей рядок у свій .bashrc:

complete -f -o default -X '!*.+(zip|udp)' unzip

Здається, за допомогою цієї пропозиції я знайду .udpфайли, але тільки якщо .zipфайлів немає. Якщо a test.zipі test.udpфайл присутній у поточному каталозі, unzip <tab>лише список .zipфайлів. Я очікував би побачити обидва файли (тобто дасть баш завершення test.).
Олексій

Ти впевнений? Я перевірив свій bash і, здається, знайшов udpі zipфайли, і файли. Ви джерело .bashrcдодавали рядок?
mkc

Я повторив у новому терміналі, і тепер unzip <tab>перелічу всі файли, навіть ті, що закінчуються іншою фразою. Тепер зовсім те, що мені потрібно.
Олексій

Дивно .. Я запускаю GNU bash версії 4.2.25 і працює як слід. На якій версії баша ви?
mkc

Чи можете ви спробувати додати два окремих рядки: complete -f -o default -X '!*.zip' unzipіcomplete -f -o default -X '!*.udp' unzip
mkc

1

Краще використовувати _filedirзамість «сирого» complete.

Виправдання

  • grep _filedir -r $(pkg-config --variable=completionsdir bash-completion) | wc -l
  • ~шляхи tilde ( ) розширюються
  • Префікси видаляються для каталогів, тобто для /home/tux/Do<TAB><TAB>списку, який ви отримуєте у відповіді, видаляється "/ home / tux" і, таким чином, набагато компактніше
  • Простіше в застосуванні та більше безвідмовно

MWE

_unzip_completor()
{
    # init bash-completion's stuff
    _init_completion || return

    # fill COMPREPLY using bash-completion's routine
    _filedir '@(zip|udp)'
}
complete -F _unzip_completor unzip
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.