Як додати шаблон для завершення 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.