¿Cómo agregar un patrón para completar bash (para descomprimir)?

11

Cuando escribo

unzip <tab>

Obtengo una lista de todos los archivos que terminan en .zip, que es el comportamiento estándar de finalización de tabulación para el unzipcomando.

Sin embargo, también quiero completar bash para los unziparchivos de lista que terminan en .udp, además de los .ziparchivos. ¿Cómo puedo lograr este comportamiento en mi local .bashrc?

Alex
fuente

Respuestas:

22

En lugar de seguir comentando ...


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

debería agregar terminación para

-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 otras palabras: complete los archivos y elimine todos los que no terminen en .zipo .udp.


Extras

Si agrega -o defaultfinalización, completará / coincidirá todos los archivos y directorios si no hay archivos que terminen en .zipo .udp.

Si agrega -o plusdirsfinalización agregará cualquier directorio además de cualquier coincidencia de archivos que terminen en .zipo .udp.

Actual

Cuando lo complete -p unzipusas obtienes el patrón actual.

De sus comentarios, suena principalmente como si faltara +o @en el patrón, como en:

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

lo que significaría coincidir con cualquier archivo que literalmente termine en.(zip|udp) . P.ej

touch 'file_test.(zip|udp)'

También eche un vistazo a esta sección del manual:

es posible, por ejemplo, extglobno está habilitado. Habilitar por:

shopt -s extglob

Verifique el estado actual de todas las shoptconfiguraciones ingresando:

shopt

Función

Si es -F somethingasí, significa que utiliza una función llamada algo para generar la lista de finalizaciones.

El _filedir_xspeces típicamente una función Debian. Puede que tengas algo como esto:

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

Lo que significa /usr/share/bash-completion/bash_completionobtener fuentes. Aquí encontrarás la función en cuestión . Algunas líneas más abajo, verá que esta función / finalización se agrega mediante una función denominada, _install_xspecpor ejemplo:

_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

Entradas manuales:


Actualización a los comentarios 1:

- No coincide debido a archivos inválidos o permisos de archivo.

Esto no debería afectar el resultado. completesolo coincide con los archivos dados por las reglas y no procesa los archivos. Si puede enumerarlos ls, deberían coincidir.

Como nota al margen, se podría agregar dicha funcionalidad mediante el uso de una función completa:

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

- Colores. ¿Por qué lsdistinguir test.zipde test.upd?

Esto no afecta complete. Los colores lsson proporcionados por $LS_COLORS. Tratar:

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

Deberías ver algo como lo *.zip=01;31que significa:

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

*.udp Por otro lado, no tiene ninguna entrada asociada, por lo que no tiene color.


Siguiente paso (debería haber sido el primero)

  1. Abra la terminal y vaya a un directorio con archivos de prueba. Tanto .zip como .udp
  2. Entrar bash --norc
  3. Entrar complete -f -X '!*.@(zip|udp)' unzip
  4. Entrar shopt -s extglob
  5. Entrar unzip <tab><tab>

¿Resultado?

Además, haga clic en editar debajo de su pregunta y agregue la salida de:

bind -V
shopt
env

Podría ser útil.

Runium
fuente
Muchas gracias por su excelente y extensa explicación, pero aún así no funciona. complete -p unzipcede complete -f -X '!*.@(zip|udp)' unzipy unzip <tab>completa el archivo llamado test.zip. Sin embargo, el directorio también contiene un archivo llamado test.updque no se encuentra al completar la pestaña unzip. ¿El hecho de los permisos de archivo o una longitud cero del archivo puede explicar este comportamiento extraño?
Alex
@Alex: Debe completarse tanto en archivos vacíos como válidos, así como en archivos donde uno no tiene permiso. ¿Es el mismo comportamiento si lo agrega a un script de prueba? Ej. 1. algún script de prueba con conjunto de ejecución:, ~/bin/testing2. complete -f -X '!*.@(zip|udp)' testing, 3. testing <tab><tab>?
Runium
@Alex: También podría actualizar Q con salida de shopt...
Runium
extglobEstá activado. El ejemplo con 'prueba' selecciona el ziparchivo solo de nuevo. Noté que test.zipse muestra en color rojo, mientras que test.updse muestra en color blanco con ls -lambos archivos vacíos con los mismos permisos, cambio de propietario y asociación de grupo. ¿Por qué lsdistinguir test.zipde test.upd? Tal vez esta es una pista sobre el problema que tengo?
Alex
@ Alex: se agregó una actualización.
Runium
3

En el archivo /etc/bash_completion, que presumiblemente está buscando en alguna parte, la finalización predeterminada, al menos para mi versión de bash(v4.2.25) es

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

Intenta cambiar toda la expresión a

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

Y agrega a tu .bash_profile

bsd
fuente
Esto no resuelve mi problema. Si lo hago y lo unzip <tab>obtengo , ni encuentra .zipni .updarchivos ni otros archivos.
Alex
Intente presionar la pestaña dos veces, vea si eso es diferente. ¿Otras terminaciones funcionan como se espera? Por ejemplo gzipcon .gzarchivos?
bsd
Golpear la pestaña dos veces no cambia nada. El uso gunzipcon .gzarchivos sólo seleccionar los archivos que terminan en .gz, pero la definición es también diferente: complete -F _filedir_xspec gunzip.
Alex
¿Obtienes el archivo /etc/bash_completionen tu .bashrc?
bsd
Pruebashopt -s extglob
Edward Falk
2

Intente agregar esta línea en su .bashrc:

complete -f -o default -X '!*.+(zip|udp)' unzip
mkc
fuente
Parece que con esta sugerencia encontraré .udparchivos, pero solo si no hay .ziparchivos presentes. Si hay un archivo test.zipy test.udpen el directorio actual, unzip <tab>solo se enumera el .ziparchivo. Esperaría ver ambos archivos (es decir, la finalización de bash daría test.).
Alex
¿Estás seguro? Revisé mi bash y parece que encuentro ambos udpy ziparchivos. ¿Fuente .bashrcdespués de agregar la línea?
mkc
Repetí en una nueva terminal, y ahora unzip <tab>enumero todos los archivos, incluso los que terminan en una frase diferente. Ahora bastante lo que necesito.
Alex
Extraño ... Estoy ejecutando GNU bash versión 4.2.25 y funciona como se esperaba. ¿En qué versión de bash estás?
mkc
¿Podría intentar agregar dos líneas separadas: complete -f -o default -X '!*.zip' unzipycomplete -f -o default -X '!*.udp' unzip
mkc
1

Mejor uso en _filedirlugar de "crudo" complete.

Justificación

  • grep _filedir -r $(pkg-config --variable=completionsdir bash-completion) | wc -l
  • los ~caminos tilde ( ) se están expandiendo
  • Los prefijos se eliminan para los directorios, es decir /home/tux/Do<TAB><TAB>, la lista que obtiene como respuesta elimina '/ home / tux' y, por lo tanto, es mucho más compacta
  • Más fácil de implementar y más seguro

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
fuente