Wie füge ich ein Muster zur Bash-Vervollständigung hinzu (zum Entpacken)?

11

Wenn ich tippe

unzip <tab>

Ich erhalte eine Liste aller Dateien, die mit enden .zip. Dies ist das Standardverhalten der Tab-Vervollständigung für den unzipBefehl.

Ich möchte jedoch auch Bash-Vervollständigung für unzipListendateien, die .udpzusätzlich zu .zipDateien enden . Wie kann ich dieses Verhalten in meiner Region erreichen .bashrc?

Alex
quelle

Antworten:

22

Anstatt weiter zu kommentieren ...


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

sollte die Vervollständigung für hinzufügen

-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

Mit anderen Worten: Vervollständigen Sie Dateien und entfernen Sie alle Dateien, die nicht auf .zipoder enden .udp.


Extras

Wenn Sie die -o defaultVervollständigung hinzufügen, werden alle Dateien und Verzeichnisse vervollständigt / abgeglichen, wenn keine Dateien mit .zipoder enden .udp.

Wenn Sie die -o plusdirsVervollständigung hinzufügen, werden zusätzlich zu den Übereinstimmungen der Dateien, die mit .zipoder enden, Verzeichnisse hinzugefügt .udp.

Aktuell

Wenn Sie verwenden, erhalten complete -p unzipSie das aktuelle Muster.

In Ihren Kommentaren klingt es meistens so , als ob Sie entweder +oder @im Muster fehlen , wie in:

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

was bedeuten würde, dass jede Datei übereinstimmt, die buchstäblich auf endet.(zip|udp) . Z.B

touch 'file_test.(zip|udp)'

Schauen Sie sich auch diesen Abschnitt des Handbuchs an:

es ist möglich, zB extglobist nicht aktiviert. Aktivieren durch:

shopt -s extglob

Überprüfen Sie den aktuellen Status aller shoptEinstellungen, indem Sie Folgendes eingeben:

shopt

Funktion

Wenn -F somethingdies der Fall ist, wird eine Funktion mit dem Namen " etwas" verwendet , um die Liste der Vervollständigungen zu generieren.

Dies _filedir_xspecist normalerweise eine Debian-Funktion. Sie könnten so etwas haben:

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

Was bedeutet /usr/share/bash-completion/bash_completion, beschafft zu werden. Hier finden Sie die betreffende Funktion . Ein paar Zeilen weiter unten sehen Sie, dass diese Funktion / Vervollständigung durch eine Funktion hinzugefügt wird, die _install_xspecz.

_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

Manuelle Eingaben:


Update auf Kommentare 1:

- Keine Übereinstimmung aufgrund ungültiger Archive oder Dateiberechtigungen.

Dies sollte das Ergebnis nicht beeinflussen. completeStimmt nur mit den durch die Regeln angegebenen Dateien überein und verarbeitet die Dateien nicht. Wenn Sie sie auflisten können ls, sollten sie übereinstimmen.

Als Randnotiz könnte man eine solche Funktionalität hinzufügen, indem man eine vollständige Funktion verwendet:

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

- Farben. Warum lsunterscheidet sich test.zipvon test.upd?

Dies hat keinen Einfluss complete. Farben von lswerden bereitgestellt von $LS_COLORS. Versuchen:

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

Sie sollten so etwas sehen, *.zip=01;31was bedeutet:

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

*.udp Auf der anderen Seite ist kein Eintrag damit verbunden, also keine Färbung.


Nächster Schritt (hätte zuerst sein sollen)

  1. Öffnen Sie das Terminal und wechseln Sie in ein Verzeichnis mit Testdateien. Sowohl .zip als auch .udp
  2. Eingeben bash --norc
  3. Eingeben complete -f -X '!*.@(zip|udp)' unzip
  4. Eingeben shopt -s extglob
  5. Eingeben unzip <tab><tab>

Ergebnis?

Klicken Sie außerdem unter Ihrer Frage auf Bearbeiten und fügen Sie die Ausgabe von:

bind -V
shopt
env

könnte hilfreich sein.

Runium
quelle
Vielen Dank für Ihre ausgezeichnete und langwierige Erklärung, aber es funktioniert immer noch nicht. complete -p unzipergibt complete -f -X '!*.@(zip|udp)' unzipund unzip <tab>vervollständigt die genannte Datei test.zip. Das Verzeichnis enthält jedoch auch eine Datei mit dem Namen, test.upddie beim Ausfüllen der Registerkarte von nicht gefunden wird unzip. Erklären die Tatsache von Dateiberechtigungen oder eine Länge der Datei von Null möglicherweise dieses seltsame Verhalten?
Alex
@Alex: Sollte sowohl für leere als auch für gültige Dateien sowie für Dateien, für die keine Berechtigung vorliegt, abgeschlossen werden. Ist es dasselbe Verhalten, wenn Sie es einem Testskript hinzufügen? ZB 1. ein Testskript mit Ausführungssatz : ~/bin/testing, 2. complete -f -X '!*.@(zip|udp)' testing, 3. testing <tab><tab>?
Runium
@ Alex: Sie können Q auch mit der Ausgabe von shopt
Runium
extglobist aktiviert. Im Beispiel mit 'Testen' wird die zipDatei nur erneut ausgewählt. Ich stelle fest, dass test.zipdies in roter Farbe angezeigt wird, während test.updes in weißer Farbe angezeigt wird ls -l, wobei beide Dateien mit denselben Berechtigungen, Eigentümerverschiebung und Gruppenzuordnung leer sind. Warum lsunterscheidet sich test.zipvon test.upd? Vielleicht ist dies ein Hinweis auf das Problem, das ich habe?
Alex
@ Alex: Ein Update wurde hinzugefügt.
Runium
3

In der Datei /etc/bash_completion, die Sie vermutlich irgendwo beziehen, ist die Standardvervollständigung, zumindest für meine Version von 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

Versuchen Sie, den gesamten Ausdruck in zu ändern

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

Und füge zu deinem hinzu .bash_profile

bsd
quelle
Dies löst mein Problem nicht. Wenn ich dies tun und beziehen es, unzip <tab>weder Funde .zipnoch .updDateien noch andere Dateien.
Alex
Versuchen Sie zweimal, die Tabulatortaste zu drücken, um festzustellen , ob dies anders ist. Funktionieren andere Abschlüsse wie erwartet? Zum Beispiel gzipmit .gzDateien?
BSD
Durch zweimaliges Drücken der Registerkarte wird nichts geändert. Bei Verwendung gunzipmit .gzDateien wählen Sie nur Dateien aus, die auf enden .gz, aber die Definition ist auch anders : complete -F _filedir_xspec gunzip.
Alex
Beziehen Sie die Datei /etc/bash_completionin Ihre .bashrc?
BSD
Versuchen Sieshopt -s extglob
Edward Falk
2

Versuchen Sie, diese Zeile in Ihre .bashrc einzufügen:

complete -f -o default -X '!*.+(zip|udp)' unzip
mkc
quelle
Es scheint, dass ich mit diesem Vorschlag .udpDateien finden werde , aber nur, wenn keine .zipDateien vorhanden sind. Wenn eine test.zipund test.udp-Datei im aktuellen Verzeichnis vorhanden ist, wird unzip <tab>nur die .zipDatei aufgelistet . Ich würde erwarten, beide Dateien zu sehen (dh die Bash-Vervollständigung würde geben test.).
Alex
Bist du sicher? Ich habe meine Bash überprüft und finde anscheinend sowohl Dateien udpals auch zipDateien. Haben Sie .bashrcnach dem Hinzufügen der Zeile Quelle ?
mkc
Ich wiederholte in einem neuen Terminal und unzip <tab>liste jetzt alle Dateien auf, auch diejenigen, die mit einer anderen Phrase enden. Jetzt ganz was ich brauche.
Alex
Seltsam .. Ich verwende GNU Bash Version 4.2.25 und funktioniert wie erwartet. Auf welcher Version von Bash bist du?
mkc
Könnten Sie versuchen, zwei separate Zeilen hinzuzufügen: complete -f -o default -X '!*.zip' unzipundcomplete -f -o default -X '!*.udp' unzip
mkc
1

Besser verwenden _filedirals "roh" complete.

Rechtfertigung

  • grep _filedir -r $(pkg-config --variable=completionsdir bash-completion) | wc -l
  • tilde ( ~) Pfade werden erweitert
  • Präfixe werden für Verzeichnisse entfernt, dh für /home/tux/Do<TAB><TAB>die Liste, die Sie als Antwort erhalten, wird '/ home / tux' entfernt und ist daher viel kompakter
  • Einfacher zu implementieren und ausfallsicherer

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
Johannes
quelle