Como adicionar padrão à conclusão do bash (para descompactar)?

11

Quando digito

unzip <tab>

Recebo uma lista de todos os arquivos que terminam em .zip, que é o comportamento padrão da conclusão da guia para o unzipcomando.

No entanto, também quero a conclusão do bash para unziparquivos de lista que terminam em .udp, além de .ziparquivos. Como posso obter esse comportamento no meu local .bashrc?

Alex
fonte

Respostas:

22

Em vez de continuar comentando ...


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

deve adicionar conclusão 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

Em outras palavras: complete os arquivos e remova tudo que não termina em .zipou .udp.


Extras

Se você adicionar a -o defaultconclusão, completará / corresponderá a todos os arquivos e diretórios, se não houver arquivos terminando em .zipou .udp.

Se você adicionar a -o plusdirsconclusão, os diretórios serão adicionados, além de correspondências de arquivos que terminam em .zipou .udp.

Atual

Quando você usa, complete -p unzipobtém o padrão atual.

A partir dos seus comentários, parece que você está perdendo um +ou mais @padrões, como em:

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

o que significa corresponder a qualquer arquivo que termine literalmente.(zip|udp) . Por exemplo

touch 'file_test.(zip|udp)'

Veja também esta seção do manual:

é possível, por exemplo, extglobnão está ativado. Ativar por:

shopt -s extglob

Verifique o status atual de todas as shoptconfigurações digitando:

shopt

Função

Se é -F somethingisso, significa que ele usa uma função chamada algo para gerar a lista de conclusões.

A _filedir_xspecé tipicamente uma função Debian. Você pode ter algo parecido com isto:

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

O que significa /usr/share/bash-completion/bash_completionobter informações. Aqui você encontrará a função em questão . Algumas linhas abaixo, você vê que esta função / conclusão é adicionada por uma função chamada _install_xspecpor exemplo:

_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 manuais:


Atualize para os comentários 1:

- Nenhuma correspondência devido a arquivos ou permissões de arquivos inválidos.

Isso não deve afetar o resultado. completecorresponde apenas aos arquivos fornecidos pelas regras e não processa os arquivos. Se você pode listá-los ls, eles devem corresponder.

Como observação lateral, pode-se adicionar essa funcionalidade usando uma função 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

- cores. Por que lsdistinguir test.zipentre test.upd?

Isso não afeta complete. As cores lssão fornecidas por $LS_COLORS. Experimentar:

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

Você deve ver algo como o *.zip=01;31que significa:

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

*.udp por outro lado, não possui nenhuma entrada associada a ela, portanto, nenhuma coloração.


Próximo passo (deveria ter sido o primeiro)

  1. Abra o terminal e vá para um diretório com arquivos de teste. .Zip e .udp
  2. Entrar bash --norc
  3. Entrar complete -f -X '!*.@(zip|udp)' unzip
  4. Entrar shopt -s extglob
  5. Entrar unzip <tab><tab>

Resultado?

Além disso, clique em editar abaixo da sua pergunta e adicione a saída de:

bind -V
shopt
env

pode ser útil.

Runium
fonte
Muito obrigado pela sua excelente e longa explicação, mas ainda assim não funciona. complete -p unzipproduz complete -f -X '!*.@(zip|udp)' unzipe unzip <tab>completa o arquivo nomeado test.zip. No entanto, o diretório também contém um arquivo test.updque não é encontrado pela conclusão da guia unzip. O fato das permissões de arquivo ou o tamanho zero do arquivo talvez explique esse comportamento estranho?
Alex
@ Alex: deve obter a conclusão em arquivos vazios e válidos, bem como em arquivos onde não há permissão. É o mesmo comportamento se você o adicionar a um script de teste? Por exemplo: 1. algum script de teste com o conjunto de execução:, ~/bin/testing2. complete -f -X '!*.@(zip|udp)' testing, 3. testing <tab><tab>?
Runium
@ Alex: Você também pode atualizar Q com saída de shopt
Runium
extglobestá ativado. O exemplo com 'testing' seleciona o ziparquivo apenas novamente. Percebo que test.zipé mostrado na cor vermelha, enquanto test.updé mostrado na cor branca com ls -l, ambos os arquivos estão vazios com as mesmas permissões, shift do proprietário e associação de grupo. Por que lsdistinguir test.zipentre test.upd? Talvez esta seja uma dica para o problema que tenho?
Alex
@ Alex: Adicionada uma atualização.
Runium
3

No arquivo /etc/bash_completionque você provavelmente está procurando em algum lugar, a conclusão padrão, pelo menos para a minha versão 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

Tente alterar a expressão inteira para

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

E adicione ao seu .bash_profile

bsd
fonte
Isso não resolve o meu problema. Se eu fizer isso e o forneça, unzip <tab>não encontra .zipnem .updarquivos nem outros arquivos.
Alex
Tente pressionar a guia duas vezes, veja se isso é diferente. Outras conclusões funcionam como esperado? Por exemplo, gzipcom .gzarquivos?
BSD
Ativar a guia duas vezes não muda nada. Usando gunzipcom .gzarquivos somente selecionar os arquivos que terminam em .gz, mas a definição também é diferente: complete -F _filedir_xspec gunzip.
Alex
Você origina o arquivo /etc/bash_completionno seu .bashrc?
BSD
Tenteshopt -s extglob
Edward Falk
2

Tente adicionar esta linha no seu .bashrc:

complete -f -o default -X '!*.+(zip|udp)' unzip
mkc
fonte
Parece que com esta sugestão vou encontrar .udparquivos, mas apenas se nenhum .ziparquivo estiver presente. Se um arquivo test.zipe test.udpestiver presente no diretório atual, unzip <tab>apenas liste o .ziparquivo. Eu esperaria ver os dois arquivos (ou seja, a conclusão do bash daria test.).
Alex
Você tem certeza? Eu verifiquei minha festança e pareço encontrar os arquivos udpe zip. Você fonte .bashrcdepois de adicionar a linha?
Mkc
Repeti em um novo terminal e agora unzip <tab>listo todos os arquivos, mesmo os que terminam em uma frase diferente. Agora é exatamente o que eu preciso.
Alex
Estranho .. Estou executando o GNU bash versão 4.2.25 e funciona conforme o esperado. Em qual versão do bash você está?
Mkc
Você poderia tentar adicionar duas linhas separadas: complete -f -o default -X '!*.zip' unzipecomplete -f -o default -X '!*.udp' unzip
mkc
1

Melhor uso em _filedirvez de "bruto" complete.

Justificação

  • grep _filedir -r $(pkg-config --variable=completionsdir bash-completion) | wc -l
  • ~caminhos til ( ) estão sendo expandidos
  • Os prefixos são removidos dos diretórios, ou seja /home/tux/Do<TAB><TAB>, a lista que você obtém como resposta remove '/ home / tux' e, portanto, é muito mais compacta
  • Mais fácil de implementar e mais à prova de falhas

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
fonte