Bash autocomplete para diretórios diferentes

4

Eu já joguei com bash autocomplete por um tempo, mas não consegui encontrar uma solução para o meu problema. Eu tenho um diretório de projeto com subpastas como este:

  • projects / ruby / project1
  • projects / ruby / project2
  • projects / rails / project3
  • projects / html / project4

Agora, quero ter um comando, chamá-lo de cdproject , em que posso cd em qualquer subpasta do diretório e subdiretórios de projetos. E esse comando deve fornecer um recurso de preenchimento automático no qual eu posso digitar cdproject pr --> TAB TAB e, em seguida, obter uma lista como ruby/project1 , ruby/project2 , rails/project3 ...

Meu problema é como lidar com os subdiretórios. O programm cdproject se parece com isso

#!/bin/bash
cd $1

O cdproject-autocompletion.bash é semelhante a este

_cdproject()
{
  local cur prev opts
  COMPREPLY=()
  cur="${COMP_WORDS[COMP_CWORD]}"
  prev="${COMP_WORDS[COMP_CWORD-1]}"
  opts=$(ls ~/Dropbox/projects)
  COMPREPLY=( $(compgen -W "${opts}" -- ${cur}) )
  return 0
}
complete -o default -o nospace -F _o  o

E dentro do meu .bash_profile , eu obtive o cdproject-autocompletion.bash com

source ~/cdproject-autocompletion.bash

Então alguém uma ideia, como conseguir isso? Talvez o opts deva retornar a estrutura do subdiretório ruby/project1 , mas o preenchimento automático deve funcionar apenas na última parte, o nome real do projeto. E não tenho ideia de como isso é possível.

    
por 23tux 06.12.2012 / 19:55

2 respostas

4

Ao ler profundamente a questão, você está procurando maneiras mais fáceis de navegar na árvore de arquivos a partir da linha de comando.

Opção 1: use CDPATH

Por exemplo, CDPATH=".:~:~/projects/ruby:~/projects/rail:~/projects/html"

Observação: algumas pessoas acham útil incluir .. em CDPATH .

Infelizmente CDPATH não (sempre) suporta autocompletar. Existem maneiras de estender bash para fazer isso. Google com os termos "CDPATH" e "autocompletion".

É certo que isto é um pouco desajeitado. Se houver um pequeno conjunto de diretórios pais que você usa, isso não é tão ruim.

Você pode ter mais sucesso com dirs , pushd e popd . Estes levam algum tempo para pegar o jeito. Observe que pushd e popd podem usar um parâmetro numérico.

Além disso: cd - retorna para o diretório anterior. Repetir o comando alterna entre os dois diretórios mais recentes.

por 26.03.2013 / 16:44
0

Isso parece ridiculamente complexo, mas é a solução que eu criei:

function gcd {
  cd $HOME/git/firefly/$1
}

function _gcdcomplete()
{
  local cmd curb cur opts

  # base dir
  git=$HOME/git/firefly/

  # last arg so far
  cur="${COMP_WORDS[COMP_CWORD]}"

  # dirname-esque, but makes "xyz/" => "xyz/" not "."
  curb=$(echo $cur | sed 's,[^/]*$,,')

  # get list of directories (use commened out line for dirs and files)
  # append '/' to directories
  # cmd="find $git$curb -maxdepth 1 -type d -printf %p/\n , -type f -print "
  cmd="find $git$curb -maxdepth 1 -type d -printf %p/\n "

  # remove base dir from list and remove extra trailing /s
  opts=$($cmd | sed s:$git:: | sed s://*$:/:)

  # generate list of completions
  COMPREPLY=( $(compgen -W "${opts}" -- ${cur}) )
  return 0;
}
complete -o nospace -F _gcdcomplete gcd
    
por 26.09.2013 / 20:50