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

42

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

    
por Volomike 30.05.2016 / 02:50

13 respostas

22

Use pushd e, em seguida, os nomes especiais dos diretórios em sua pilha de diretórios: ~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 pushd desta forma é carregar sua lista de diretórios, então adicionar mais um diretório para ser seu diretório atual, e então você pode saltar entre os números estáticos sem afetar a posição dos diretórios na sua pilha.

É importante notar também que cd - irá levá-lo ao último diretório em que você estava. Então, cd ~- .

A vantagem de ~- sobre - é que - é específico de cd , enquanto ~- é expandido pelo seu 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/
    
por 31.05.2016 / 11:12
38
O push do bash construído com as opções + e - pode girar a pilha de diretórios. A sintaxe pode ser um pouco confusa, talvez porque essa pilha é uma matriz baseada em zero . Essas funções de invólucro simples 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 dirs.

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-o) quatro vezes:

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

Saída:

/bin
/etc
/home
/tmp

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

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

Saída:

/home
/etc
/bin
/tmp

Uma observação sobre a resposta cd - : Wildcard ajudou a ilustrar como cd - não usa a matriz $ DIRSTACK (usa o $ OLDPW variável), para que cd - não efetue $ DIRSTACK como uma troca baseada em pilha. Para corrigir isso, aqui está uma simples função $ DIRSTACK baseada em swap :

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

Saída:

/bin /tmp
/etc /bin /tmp
/lib /etc /bin /tmp
/home /lib /etc /bin /tmp
/lib /home /etc /bin /tmp
/home /lib /etc /bin /tmp
    
por 30.05.2016 / 05:39
12

Sugiro que você instale fasd . Ele permite que você pule rapidamente para qualquer diretório em que já tenha estado digitando apenas uma pequena fração de seu nome.

Exemplo: se você visitou /home/someName/scripts/ , pode pular para lá apenas digitando z scr , por exemplo. É muito mais conveniente lembrar-se da ordem na pilha de histórico de algo similar.

    
por 30.05.2016 / 11:05
10

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

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

Você pode voltar e avançar entre diretórios da seguinte forma:

blue$ cd ~/green
green$ cd -
blue$ cd -
green$
    
por 31.05.2016 / 10:20
6

Eu escrevi um script chamado xyzzy para 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

A maneira como uso isso é copiar para a pasta /usr/bin e, em seguida, chmod a+x para ela. Em seguida, edito meu arquivo ~/.bashrc de conta raiz e usuário para incluir essas linhas na parte inferior:

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

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

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

xyzzy this

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

xyzzy show

... para listar os diretórios salvos atualmente. Para mudar para um diretório, tenho duas escolhas. Uma opção é especificar o caminho por í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 o número do índice e fazer:

xyzzy

... para fazer um loop em cada diretório conforme necessário. Para mais comandos que você pode fazer, digite:

xyzzy help

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

Observe que o xyzzy é uma referência à aventura de texto Caverna da Coluna , em que é feita a digitação xyzzy permitiria alternar entre duas salas no jogo para evitar grues.

    
por 30.05.2016 / 02:50
5

Há também cd_func de Petar Marinov, é basicamente cd com um histórico de até 10 entradas: link

# 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

Use um cd -- para mostrar uma lista dos últimos até 10 diretórios que você usou cd ed e cd -N (onde N é o índice da entrada) para ir para lá.

    
por 30.05.2016 / 08:20
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ê foi para /home/morfik/Desktop/ e /home/morfik/something/ , você pode alternar entre os diretórios muito rapidamente. Não importa quantas entradas você tenha no histórico de shell, mas quando você tem muito, use uma expressão melhor, por exemplo, cd /home/morf e aqui pressione as setas para cima / para baixo no teclado.

Existe também outra maneira de alcançar a solução. Neste caso você tem que usar tmux e FZF . Então você apenas faz um hotkey, por exemplo ctrl-r, e quando você pressiona, sua janela atual será dividida e você verá isto:

Agoravocêpodeusarexpressõesparapesquisarnalista.Acabeidedigitar^cd/media,queretornaapenasasentradasquecomeçamcomafrase.Claro,vocêpodeapenasdigitar'cd'homeparacorresponderaocomandoetambémonomedodiretóriointeiro(nãoocaminho,apenasonome):

    
por 31.05.2016 / 10:39
4

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

O objetivo principal é a digitação quase mínima (por exemplo, d5 pula para o número de diretório 5 no pool) para alternar entre os diretórios no pool. Também queremos facilitar a adição / remoção de diretórios para / do 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ê empurra um diretório na pilha, ele é adicionado ao pool numerado na posição 0 (o diretório atual) e você pode alternar (alterar diretórios) usando muito pouca digitação ( d<N> ) e pode ver seu pool atual numerado a qualquer momento apenas digitando d .

Alguns exemplos de uso desses aliases:

Exibe o pool de diretas numeradas (o diretório atual é # 0)

$ d
 0  /tmp
 1  /
 2  /usr

Alternar entre dirs: use d<N>

$ d2
$ pwd
/usr

Adicione 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 / estourar o diretório top (atual) do pool

$ po
$ d
 0  /
 1  /var/log
 2  /usr
    
por 31.05.2016 / 09:57
4

Eu uso um pequeno script chamado z [link] , que também pode ser interessante, embora 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.
    
por 31.05.2016 / 02:05
2

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

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

Isso fornecerá um menu navegável de teclas de seta interativo baseado em ncurses para selecionar um diretório para cd to.

Se você não usou pushd na sessão atual do shell, a lista de diretórios no menu começa com apenas uma entrada, seu diretório atual. Se houver apenas uma entrada, esse dirselect alias irá apenas cd para ele sem a tela do menu, de forma que ele efetivamente não faça nada (exceto impedir que cd - faça algo útil)

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

Você pode preencher previamente a pilha pushd fazendo algo parecido com o seguinte em .bashrc ou ~/.bash_profile :

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

Você pode remover entradas com popd ou popd -n .

Veja help pushd , help popd e help dirs no bash para mais informações. E, claro, man iselect .

BTW, iselect provavelmente está disponível como pré-empacotado para sua distro. É para o Debian e Ubuntu, etc, e provavelmente para outros também.

    
por 30.05.2016 / 07:25
2

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

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

E assim, quando eu quero ir para o diretório da página inicial do Apache, basta digitar cdw como eu atendi em Equivalente de apelido para um link simbólico? .

    
por 30.05.2016 / 17:09
2

Estou usando o salto 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 pular facilmente para outro diretório:

jump reports

Ele suporta autocompletar para bash e zsh.

Editar (em resposta a @Joe): o binário jump-bin é armazenado em /usr/local/bin , e 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 bash jump que chama jump-bin .

    
por 31.05.2016 / 12:39
2

Eu uso alias para navegar. Se você tiver poucos diretórios que são acessados freqüentemente, simplesmente defina aliases. Por exemplo,

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

Então, simplesmente

e 

leva você para /etc .

    
por 31.05.2016 / 15:29