O que é uma maneira rápida de alternar entre vários diretórios para administração do sistema?

46

O que é uma maneira rápida de alternar entre vários diretórios para administração do sistema? Quero dizer, eu posso usar pushd .e popdalternar, mas e se eu quiser armazenar múltiplos e percorrê-los, em vez de removê-los permanentemente da parte inferior da pilha?

Volomike
fonte
$CDPATHpossivelmente?
roaima 30/05
6
oh meu Deus - acabei de aprender sobre o Google cd -depois de instigado a partir dessa pergunta.
Nacht - Restabelece Monica
@ Nacht: Como você navegou na estrutura do arquivo antes?
Loneboat
1
Fez em cdtodos os lugares à mão. Foi doloroso. Conclusão automática usada com a tecla tab.
Volomike 31/05
1
Talvez você queira tentar . Extremamente útil quando você pula bastante dentro do mesmo par de dirs.
Rolf

Respostas:

28

Use pushde depois os nomes especiais para os diretórios em sua pilha diretório: ~1, ~2, etc.

Exemplo:

tmp $ dirs -v
 0  /tmp
 1  /tmp/scripts
 2  /tmp/photos
 3  /tmp/music
 4  /tmp/pictures
tmp $ cd ~3
music $ dirs -v
 0  /tmp/music
 1  /tmp/scripts
 2  /tmp/photos
 3  /tmp/music
 4  /tmp/pictures
music $ cd ~2
photos $ cd ~4
pictures $ cd ~3
music $ cd ~1
scripts $ 

A maneira mais eficaz de usar pushddessa maneira é carregar sua lista de diretórios, adicionar mais um diretório ao diretório atual e então você pode pular entre os números estáticos sem afetar a posição dos diretórios na pilha.


É importante notar também que cd -irá levá-lo para o último diretório que você estava em. Assim será cd ~-.

A vantagem ~-sobre apenas -é que -é específico para cd, ao passo que ~-é expandida pelo shell da mesma forma que ~1, ~2, etc, são. Isso é útil ao copiar um arquivo entre caminhos de diretório muito longos; por exemplo:

cd /very/long/path/to/some/directory/
cd /another/long/path/to/where/the/source/file/is/
cp myfile ~-

O acima é equivalente a:

cp /another/long/path/to/where/the/source/file/is/myfile /very/long/path/to/some/directory/
Curinga
fonte
1
Também pode usarcd -
Volomike
cd -age como um quarto adiante DROP DUP, por exemplo, se alguém começa com no diretório a , com a pilha abcd , a cd -altera a pilha para bbcd . Talvez isso seja um bashbug, pois um segundo cd -altera a pilha novamente para abcd . A partir disso, podemos inferir que cd -utiliza alguma estrutura de dados separada para armazenar o diretório anterior, além de alterar a pilha.
agc 31/05
3
@agc, cd -usa $OLDPWDe nada mais.
Curinga
Talvez cd -fosse o recurso bash anterior , depois eles adicionaram uma pilha, mas temiam quebrar o código antigo mais do que queriam um design mais simples. A correção para anterior, cd -age como um Quarto OLDPWD @ SWAP OLDPWD ! DUP . Ao contrário cd foo, o cd -imprime o nome do diretório trocado.
agc 31/05
Ou sempre há o empacotador de pushd interativo (outras respostas para essa pergunta incluem salto automático etc. etc.).
inútil
42

bashO built-in pushdcom as opções +e -pode girar a pilha de diretórios. A sintaxe pode ser um pouco confusa, talvez porque essa pilha seja uma matriz com base em zero . Essas funções simples do wrapper percorrem a pilha de diretórios:

# cd to next     directory in stack (left  rotate)
ncd(){ pushd +1 > /dev/null ; }
# cd to previous directory in stack (right rotate)
pcd(){ pushd -0 > /dev/null ; }

Teste: configure uma pilha de quatro diretórios.

dirs -c   # clear directory stack
cd /home ; pushd /etc ; pushd /bin ; pushd /tmp

Agora / tmp é o diretório atual e a pilha se parece com:

/tmp /bin /etc /home

Mude para o próximo diretório na pilha (e mostre) quatro vezes:

ncd ; pwd ; ncd ; pwd ; ncd ; pwd ; ncd ; pwd

Resultado:

/bin
/etc
/home
/tmp

Mude para o diretório anterior na pilha ((e mostre)) quatro vezes:

pcd ; pwd ; pcd ; pwd ; pcd ; pwd ; pcd ; pwd

Resultado:

/home
/etc
/bin
/tmp

Uma observação sobre cd -: a resposta do curinga ajudou a ilustrar como cd -não usa o array $ DIRSTACK ((usa a variável $ OLDPW )), de modo que cd -não afeta o $ DIRSTACK da maneira que uma troca baseada em pilha deveria. Para corrigir isso, aqui está uma simples função de troca baseada em $ DIRSTACK :

scd() { { pushd ${DIRSTACK[1]} ; popd -n +2 ; } > /dev/null ; }

Teste:

dirs -c; cd /tmp; \
pushd /bin; \
pushd /etc; \
pushd /lib; \
pushd /home; \
scd; dirs; scd; dirs

Resultado:

/bin /tmp
/etc /bin /tmp
/lib /etc /bin /tmp
/home /lib /etc /bin /tmp
/lib /home /etc /bin /tmp
/home /lib /etc /bin /tmp
agc
fonte
Minha frustração é que eu quero colocar itens na pilha e mantê-los lá até eu optar por limpar a pilha. Dessa forma, eu posso empurrar, empurrar, empurrar e percorrer cada um dos três dirs, conforme necessário. Digamos, por exemplo, que eu preciso alternar entre três diretórios como se fossem guias do navegador e ir e voltar, até fechar uma guia. Isso aborda isso de uma maneira de linha de comando?
Volomike 30/05
5
Sim, acredito que sim, experimente. Para remover o item superior, popdremova-o sem alterar os diretórios, remova-o popd -n. Para limpar a pilha faça dirs -c. Pena que os designers do bash enterraram essas funções úteis em sintaxe não intuitiva. Veja man bashem pushd, dirsetc.
agc 30/05
Trabalho! E estava claro como lama nos documentos. Gosto da simplicidade, agora que conheço a técnica.
Volomike 30/05
13

Eu sugiro que você instale o fasd . Permite-lhe saltar rapidamente para qualquer diretório em que você já esteja digitando apenas uma pequena fração do nome.

Exemplo: se você visitou /home/someName/scripts/, pode pular para lá apenas digitando, z scrpor exemplo. É muito mais conveniente do que lembrar a ordem na pilha do histórico ou algo semelhante.

kaqqao
fonte
10

Quando você está em cdalgum lugar, o Bash armazena no diretório de trabalho antigo uma variável de ambiente $OLDPWD,.

Você pode voltar para esse diretório com cd -, que é equivalente a cd "$OLDPWD".

Você pode alternar entre diretórios da seguinte maneira:

blue$ cd ~/green
green$ cd -
blue$ cd -
green$
RJHunter
fonte
6

Eu escrevi um script chamado xyzzypara fazer isso:

#!/bin/bash

i="$1"
i=$((${i//[^0-9]/}))
i="$(($i-1+0))"

b="$2"
b=$((${b//[^0-9]/}))
b="$(($b-1+0))"

if [ -z "$XYZZY_INDEX" ]; then
    XYZZY_INDEX="$((-1))"
fi

if [ ! -f "/tmp/xyzzy.list" ]; then
    touch /tmp/xyzzy.list
    chmod a+rw /tmp/xyzzy.list
fi
readarray -t MYLIST < /tmp/xyzzy.list

showHelp(){
read -r -d '' MYHELP <<'EOB'
xyzzy 1.0

A command for manipulating escape routes from grues. Otherwise known as a useful system admin
tool for storing current directories and cycling through them rapidly. You'll wonder why this
wasn't created many moons ago.

Usage: xyzzy [options]

help/-h/--help      Show the help.

this/-t/--this      Store the current directory in /tmp/xyzzy.list

begone/-b/--begone  Clear the /tmp/xyzzy.list file. However, succeed with a number and
            it clears just that item from the stored list.

show/-s/--show      Show the list of stored directories from /tmp/xyzzy.list

. #         Use a number to 'cd' to that directory item in the stored list. This syntax is odd:

            . xyzzy 2

            ...would change to the second directory in the list

. [no options]      Use the command alone and it cd cycles through the next item in the stored 
            list, repeating to the top when it gets to the bottom. The dot and space before xyzzy
            is required in order for the command to run in the current shell and not a subshell:

            . xyzzy

Note that you can avoid the odd dot syntax by adding this to your ~/.bashrc file:

  alias xyzzy=". xyzzy"

and then you can do "xyzzy" to cycle through directories, or "xyzzy {number}" to go to a
specific one.

May you never encounter another grue.

Copyright (c) 2016, Mike McKee <https://github.com/volomike>
EOB
    echo -e "$MYHELP\n"
}

storeThis(){
    echo -e "With a stroke of your wand, you magically created the new escape route: $PWD"
    echo "$PWD" >> /tmp/xyzzy.list
    chmod a+rw /tmp/xyzzy.list
}

begoneList(){
    if [[ "$b" == "-1" ]]; then
        echo "POOF! Your escape routes are gone. We bless your soul from the ever-present grues!"
        >/tmp/xyzzy.list
        chmod a+rw /tmp/xyzzy.list
    else
        echo -n "Waving your wand in the dark, you successfully manage to remove one of your escape routes: "
        echo "${MYLIST[${b}]}"
        >/tmp/xyzzy.list
        chmod a+rw /tmp/xyzzy.list
        for x in "${MYLIST[@]}"; do
            if [[ ! "$x" == "${MYLIST[${b}]}" ]]; then
                echo "$x" >> /tmp/xyzzy.list
            fi
        done
    fi
}

showList(){
    echo -e "These are your escape routes:\n"
    cat /tmp/xyzzy.list
}

cycleNext(){
    MAXLINES=${#MYLIST[@]}
    XYZZY_INDEX=$((XYZZY_INDEX+1))
    if [[ $XYZZY_INDEX > $(($MAXLINES - 1)) ]]; then
        XYZZY_INDEX=0
    fi
    MYLINE="${MYLIST[${XYZZY_INDEX}]}"
    cd "$MYLINE";
}

switchDir(){
    MYLINE="${MYLIST[${i}]}"
    cd "$MYLINE";
}

if [[ "$@" == "" ]];
then
    cycleNext
fi;

while [[ "$@" > 0 ]]; do case $1 in
    help) showHelp;;
    --help) showHelp;;
    -h) showHelp;;
    show) showList;;
    -s) showList;;
    --show) showList;;
    list) showList;;
    this) storeThis;;
    --this) storeThis;;
    -t) storeThis;;
    begone) begoneList;;
    --begone) begoneList;;
    *) switchDir;;
    esac; shift
done

export XYZZY_INDEX

O jeito que eu uso isso é copiar para a /usr/binpasta e depois para a pasta chmod a+x. Em seguida, edito meu ~/.bashrcarquivo de conta raiz e de usuário para incluir estas linhas na parte inferior:

alias xyzzy='. xyzzy'
alias xy='. xyzzy'

O 'xy' é uma forma abreviada do comando para digitação mais rápida.

Em seguida, posso armazenar o diretório atual na lista com ...

xyzzy this

... e repita conforme necessário. Depois de preencher esta lista com os diretórios de que preciso, eles permanecem lá até eu reiniciar o computador, porque é quando o / tmp é limpo novamente. Eu posso então digitar ...

xyzzy show

... para listar os diretórios atualmente salvos. Para mudar para um diretório, tenho duas opções. Uma opção é especificar o caminho pelo índice (e é um índice baseado em 1) da seguinte forma:

xyzzy 2

... que mudaria para o diretório que é o segundo item da lista. Ou, eu poderia deixar de fora o número do índice e apenas:

xyzzy

... para fazer um loop através de cada diretório que eu precisar. Para mais comandos que você pode executar, digite:

xyzzy help

Obviamente, o trabalho é mais divertido com as declarações de eco tolas que adicionei.

Observe que xyzzy é uma referência à aventura de texto da Caverna Collosal , onde a digitação de xyzzy permite alternar entre duas salas no jogo para evitar pavor.

Volomike
fonte
2
+1 Comecei a brincar com isso. É bom, mas parece falhar se nenhum diretório foi adicionado ainda e você digita apenas xyzzy. Precisa de mais um teste para MAXLINES -eq 0 em cyclenext ().
Joe
5

Eu uso um pequeno script chamado z [link] , que também pode ser interessante, mesmo que não faça exatamente o que você pediu.

NAME
       z - jump around

SYNOPSIS
       z [-chlrtx] [regex1 regex2 ... regexn]

AVAILABILITY
       bash, zsh

DESCRIPTION
       Tracks your most used directories, based on 'frecency'.

       After  a  short  learning  phase, z will take you to the most 'frecent'
       directory that matches ALL of the regexes given on the command line, in
       order.

       For example, z foo bar would match /foo/bar but not /bar/foo.
Graipher
fonte
Talvez eu tenha perdido alguma coisa, mas onde encontro o próprio script z?
Joe
Desculpe, o link estava no z. Será editado para facilitar a visualização.
Graipher
5

Há também cd_funcde Petar Marinov, basicamente cdcom um histórico de até 10 entradas: http://linuxgazette.net/109/misc/marinov/acd_func.html

# do ". acd_func.sh"
# acd_func 1.0.5, 10-nov-2004
# petar marinov, http:/geocities.com/h2428, this is public domain

cd_func ()
{
  local x2 the_new_dir adir index
  local -i cnt

  if [[ $1 ==  "--" ]]; then
    dirs -v
    return 0
  fi

  the_new_dir=$1
  [[ -z $1 ]] && the_new_dir=$HOME

  if [[ ${the_new_dir:0:1} == '-' ]]; then
    #
    # Extract dir N from dirs
    index=${the_new_dir:1}
    [[ -z $index ]] && index=1
    adir=$(dirs +$index)
    [[ -z $adir ]] && return 1
    the_new_dir=$adir
  fi

  #
  # '~' has to be substituted by ${HOME}
  [[ ${the_new_dir:0:1} == '~' ]] && the_new_dir="${HOME}${the_new_dir:1}"

  #
  # Now change to the new dir and add to the top of the stack
  pushd "${the_new_dir}" > /dev/null
  [[ $? -ne 0 ]] && return 1
  the_new_dir=$(pwd)

  #
  # Trim down everything beyond 11th entry
  popd -n +11 2>/dev/null 1>/dev/null

  #
  # Remove any other occurence of this dir, skipping the top of the stack
  for ((cnt=1; cnt <= 10; cnt++)); do
    x2=$(dirs +${cnt} 2>/dev/null)
    [[ $? -ne 0 ]] && return 0
    [[ ${x2:0:1} == '~' ]] && x2="${HOME}${x2:1}"
    if [[ "${x2}" == "${the_new_dir}" ]]; then
      popd -n +$cnt 2>/dev/null 1>/dev/null
      cnt=cnt-1
    fi
  done

  return 0
}

alias cd=cd_func

if [[ $BASH_VERSION > "2.05a" ]]; then
  # ctrl+w shows the menu
  bind -x "\"\C-w\":cd_func -- ;"
fi

Simplesmente use cd --para mostrar uma lista dos últimos 10 diretórios nos quais você cdeditou e cd -N(onde Nestá o índice da entrada) para ir para lá.

phk
fonte
4

Eu uso principalmente o ZSH com o perfil oh-my-zsh . Você pode digitar em um terminal a seguinte correspondência:

# cd /ho

Então você pode simplesmente usar as setas (para cima e para baixo) para percorrer todo o histórico do shell, que mostra apenas as entradas que começam com os caracteres acima. Então, por exemplo, se você acessou /home/morfik/Desktop/e /home/morfik/something/, pode alternar entre os diretórios muito rapidamente. Não importa quantas entradas no histórico do shell você tenha, mas quando tiver muito, use uma expressão melhor, ou seja, cd /home/morfe aqui pressione as setas para cima / para baixo no teclado.

Há também outra maneira de alcançar a solução. Nesse caso, você precisa usar o tmux e o FZF . Então você apenas cria uma tecla de atalho, por exemplo, ctrl-r, e quando você pressiona, sua janela atual será dividida e você verá o seguinte:

insira a descrição da imagem aqui

Agora você pode usar expressões para pesquisar na lista. Eu apenas digitei ^cd /media, que retorna apenas as entradas que começam com a frase. Obviamente, você pode apenas digitar 'cd 'homepara corresponder ao comando e também ao nome do diretório inteiro (não caminho, apenas nome):

insira a descrição da imagem aqui

Mikhail Morfikov
fonte
4

Você pode conseguir isso com vários aliases em seu ~/.bashrc(ou equivalente)

O objetivo principal é digitar quase o mínimo (por exemplo, d5pula para o diretório número 5 no pool) para alternar entre os diretórios no pool. Também queremos facilitar a adição / remoção de diretórios de / para o pool:

alias pd=pushd
alias po=popd
alias d='dirs -v'
alias d0=d
alias d1='pd +1'
alias d2='pd +2'
alias d3='pd +3'
alias d4='pd +4'
alias d5='pd +5'
alias d6='pd +6'
alias d7='pd +7'
alias d8='pd +8'
alias d9='pd +9'
alias d10='pd +10'
# -- feel free to add more aliases if your typical dir pool is larger than 10

Agora, toda vez que você pressiona um diretório na pilha, ele é adicionado ao pool numerado na posição 0 (o diretório atual) e você pode pular (alternar diretórios) usando muito pouca digitação ( d<N>) e pode visualizar seu pool atual numerado em qualquer hora apenas digitando d.

Alguns exemplos de uso desses aliases:

Exibir o conjunto de diretórios numerado (o diretório atual é # 0)

$ d
 0  /tmp
 1  /
 2  /usr

Alternar entre dirs: use d<N>

$ d2
$ pwd
/usr

Adicionar um novo diretório ao pool

$ pd /var/log
$ d
 0  /var/log
 1  /usr
 2  /tmp
 3  /

Pule um pouco mais:

$ d3
$ pwd
/

$ d3
$ pwd
/tmp

$ d
 0  /tmp
 1  /
 2  /var/log
 3  /usr

Remover / pop do diretório superior (atual) da piscina

$ po
$ d
 0  /
 1  /var/log
 2  /usr
arielf
fonte
2

Se você tiver o iselect instalado, poderá fazer algo assim:

$ alias dirselect='cd $(iselect -a $(dirs -l -p | sort -u))'
$ dirselect

Isso fornecerá a você um menu navegável interativo com teclas de seta, em tela cheia, para selecionar um diretório cdpara.

Se você não usou pushdna sessão atual do shell, a lista de diretórios no menu começa com apenas uma entrada, o diretório atual. Se houver apenas uma entrada, esse dirselectalias será feito cdsem a tela do menu, portanto, ele efetivamente não fará nada (exceto impedir cd -que seja útil)

Para adicionar um novo diretório à lista, use pushd dir(ou pushd -n dirpara adicionar um diretório sem cd- ao mesmo tempo)

Você pode preencher previamente a pushdpilha fazendo algo como o seguinte em seu .bashrcou ~/.bash_profile:

for d in /var/tmp /tmp /path/to/somewhere/interesting ; do 
  pushd -n "$d" > /dev/null
done

Você pode remover entradas com popdou popd -n.

Ver help pushd, help popde help dirsem bash para mais informações. E, claro man iselect,.

BTW, iselectprovavelmente está disponível pré-embalado para sua distribuição. É para Debian e Ubuntu etc, e provavelmente para outros também.

cas
fonte
2

Se você possui 5 ou 10 diretórios, usa muito e não se importa necessariamente com os diretórios 5 ou 10 usados ​​recentemente , configure alguns aliases de comando como

alias cdw="cd /var/www/html" 

E então, quando eu quero ir para o diretório da página inicial do Apache, basta digitar cdwcomo respondi no equivalente de alias para um link simbólico? .

Mark Stewart
fonte
2

Estou usando o jump para alterar rapidamente o diretório de trabalho.

Para adicionar o diretório atual:

jump -a [bookmark-name]

Para listar todos os seus favoritos:

jump -l

por exemplo:

------------------------------------------------------------------
 Bookmark    Path                                                 
------------------------------------------------------------------
 reports     ~/mydir/documents/reports
 projects    ~/documents/projects
 dl          ~/Downloads                     
------------------------------------------------------------------

Agora você pode facilmente pular para outro diretório:

jump reports

Ele suporta o preenchimento automático para o bash e o zsh.


Editar (em resposta a @Joe): o binário jump-biné armazenado /usr/local/bine, com o script de integração do bash (no meu PC localizado em /var/lib/gems/1.9.1/gems/jump-0.4.1/bash_integration/shell_driver), ele cria uma função do bash jumpque chama jump-bin.

agold
fonte
Onde mora o comando jump? Eu não o tenho e não vejo imediatamente onde obtê-lo.
Joe
2

Eu uso aliaspara navegar. Se você tiver poucos diretórios que são acessados ​​com frequência, basta definir aliases. Por exemplo,

alias e='cd /etc'
alias h='cd /home'
alias al='cd /var/log/apache2/'

Então simplesmente

e 

levará você para /etc.

Besta de Segurança
fonte