Comment ajouter un motif à l'achèvement de bash (pour décompresser)?

11

Quand je tape

unzip <tab>

J'obtiens une liste de tous les fichiers se terminant par .zip, qui est le comportement standard de complétion de tabulation pour la unzipcommande.

Cependant, je souhaite également l'achèvement de bash pour les unzipfichiers de liste se terminant par .udp, en plus des .zipfichiers. Comment puis-je obtenir ce comportement dans ma section locale .bashrc?

Alex
la source

Réponses:

22

Au lieu de continuer à commenter…


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

devrait ajouter l'achèvement pour

-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

En d'autres termes: complétez les fichiers et supprimez tous ceux qui ne se terminent pas par .zipou .udp.


Suppléments

Si vous ajoutez la -o defaultcomplétion, tous les fichiers et répertoires seront complétés / correspondront s'il n'y a aucun fichier se terminant par .zipou .udp.

Si vous ajoutez -o plusdirsachèvement, vous ajouterez des répertoires en plus des correspondances de fichiers se terminant par .zipou .udp.

Courant

Lorsque vous utilisez, complete -p unzipvous obtenez le modèle actuel.

De vos commentaires il semble surtout que vous manquez soit +ou @dans le modèle, comme dans:

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

ce qui signifierait correspondre à n'importe quel fichier se terminant littéralement par.(zip|udp) . Par exemple

touch 'file_test.(zip|udp)'

Jetez également un œil à cette section du manuel:

il est possible par exemple extglobn'est pas activé. Activer par:

shopt -s extglob

Vérifiez l'état actuel de tous les shoptparamètres en entrant:

shopt

Fonction

Si c'est le cas, -F somethingcela signifie qu'il utilise une fonction nommée quelque chose pour générer la liste des achèvements.

Il _filedir_xspecs'agit généralement d'une fonction Debian. Vous pourriez avoir quelque chose comme ça:

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

Ce qui signifie /usr/share/bash-completion/bash_completionse sourcer. Vous trouverez ici la fonction en question . Quelques lignes plus loin, vous voyez que cette fonction / complétion est ajoutée par une fonction nommée _install_xspecpar exemple:

_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

Entrées manuelles:


Mise à jour des commentaires 1:

- Aucune correspondance en raison d'archives non valides ou d'autorisations de fichiers.

Cela ne devrait pas affecter le résultat. completene correspond qu'aux fichiers fournis par les règles et ne fait aucun traitement des fichiers. Si vous pouvez les répertorier ls, ils doivent correspondre.

En remarque, on pourrait ajouter une telle fonctionnalité en utilisant une fonction complète:

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

- Couleurs. Pourquoi ne lsdistinguer test.zipde test.upd?

Cela n'affecte pas complete. Les couleurs lssont fournies par $LS_COLORS. Essayer:

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

Vous devriez voir quelque chose comme *.zip=01;31ce qui signifie:

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

*.udp d'autre part n'a pas d'entrée associée, donc pas de coloration.


Étape suivante (aurait dû être la première)

  1. Ouvrez le terminal et accédez à un répertoire contenant des fichiers de test. .Zip et .udp
  2. Entrer bash --norc
  3. Entrer complete -f -X '!*.@(zip|udp)' unzip
  4. Entrer shopt -s extglob
  5. Entrer unzip <tab><tab>

Résultat?

Cliquez également sur modifier sous votre question et ajoutez la sortie de:

bind -V
shopt
env

pourrait être utile.

Runium
la source
Merci beaucoup pour votre excellente et longue explication, mais cela ne fonctionne toujours pas. complete -p unzipdonne complete -f -X '!*.@(zip|udp)' unzipet unzip <tab>complète le fichier nommé test.zip. Cependant, le répertoire contient également un fichier nommé test.updqui n'est pas trouvé par la complétion de l'onglet de unzip. Le fait d'autorisations de fichier ou d'une longueur nulle du fichier peut-il expliquer ce comportement étrange?
Alex
@Alex: devrait être terminé sur les fichiers vides et valides, ainsi que sur les fichiers où l'on n'a pas l'autorisation. Est-ce le même comportement si vous l'ajoutez à un script de test? Par exemple: 1. un script de test avec un ensemble d'exécution:, ~/bin/testing2. complete -f -X '!*.@(zip|udp)' testing, 3. testing <tab><tab>?
Runium
@Alex: Vous pouvez également mettre à jour Q avec une sortie de shopt
Runium
extglobest activé. L'exemple avec «testing» ne sélectionne à nouveau le zipfichier. Je remarque que cela test.zipest indiqué en rouge, tandis que test.updest affiché en blanc avec ls -l, les deux fichiers vides avec les mêmes autorisations, le changement de propriétaire et l'association de groupe. Pourquoi ne lsdistinguer test.zipde test.upd? C'est peut-être un indice du problème que j'ai?
Alex
@Alex: Ajout d'une mise à jour.
Runium
3

Dans le fichier /etc/bash_completionque vous recherchez probablement quelque part, l'achèvement par défaut, au moins pour ma version de bash(v4.2.25) est

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

Essayez de changer l'expression entière en

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

Et ajoutez à votre .bash_profile

bsd
la source
Cela ne résout pas mon problème. Si je le fais et que je le source, je unzip <tab>ne trouve .zipni .updfichiers ni autres fichiers.
Alex
Essayez d'appuyer deux fois sur l' onglet pour voir si c'est différent. Les autres achèvements fonctionnent-ils comme prévu? Par exemple gzipavec des .gzfichiers?
bsd
Appuyer deux fois sur l'onglet ne change rien. L' utilisation gunzipdes .gzfichiers de sélectionner des fichiers se terminant seulement .gz, mais la définition est également différente: complete -F _filedir_xspec gunzip.
Alex
Sourcez-vous le fichier /etc/bash_completiondans votre .bashrc?
bsd
Essayezshopt -s extglob
Edward Falk
2

Essayez d'ajouter cette ligne dans votre .bashrc:

complete -f -o default -X '!*.+(zip|udp)' unzip
mkc
la source
Il semble qu'avec cette suggestion, je vais trouver des .udpfichiers, mais uniquement si aucun .zipfichier n'est présent. Si un fichier test.zipet test.udpest présent dans le répertoire en cours, unzip <tab>répertorie uniquement le .zipfichier. Je m'attendrais à voir les deux fichiers (c'est-à-dire que l'achèvement de bash donnerait test.).
Alex
Êtes-vous sûr? J'ai vérifié mon bash et je semble trouver les deux fichiers udpet zip. Avez-vous source .bashrcaprès avoir ajouté la ligne?
mkc
J'ai répété dans un nouveau terminal, et unzip <tab>liste maintenant tous les fichiers, même ceux se terminant par une phrase différente. Maintenant tout à fait ce dont j'ai besoin.
Alex
Étrange .. J'utilise GNU bash version 4.2.25 et fonctionne comme prévu. Sur quelle version de bash êtes-vous?
mkc
Pourriez-vous essayer d'ajouter deux lignes distinctes: complete -f -o default -X '!*.zip' unzipetcomplete -f -o default -X '!*.udp' unzip
mkc
1

Une meilleure utilisation _filedirau lieu de "brut" complete.

Justification

  • grep _filedir -r $(pkg-config --variable=completionsdir bash-completion) | wc -l
  • les ~chemins tilde ( ) sont développés
  • Les préfixes sont supprimés pour les répertoires, c'est-à-dire pour /home/tux/Do<TAB><TAB>, la liste que vous obtenez en réponse supprime «/ home / tux» et est donc beaucoup plus compacte
  • Plus facile à mettre en œuvre et plus sûr

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
la source