Como você cd para o diretório de outra janela de tela?

0

O gnome-terminal tem um ótimo recurso onde abrir uma nova aba ou janela inicia o novo shell com cwd = o cwd da janela focada anteriormente.

Normalmente, executo a tela GNU em uma das guias do meu terminal gnome. Em parte para a rolagem, em parte para a exibição compacta e enumarada de 5 a 10 janelas, em parte para a rápida digitação para alternar para uma guia específica ou anterior.

Mas eu comecei a desejar poder gravar em uma janela para o CWD de outra janela. A questão é como?

(BTW, é um Q & self-A do stackexchange uma maneira apropriada de compartilhar um apelido puro, função shell ou hackear assim que eu criei? Eu não tenho um bloco, e eu não acho twitter ou facebook seriam boas opções.)

    
por Peter Cordes 06.02.2015 / 16:07

1 resposta

0

Este método é portátil para qualquer sistema Unix, mas depende da funcionalidade do cd -P do GNU bash para torná-lo não feio.

Coloque isto (ou a outra versão abaixo, que preserva diretórios lógicos) no seu ~/.bashrc (ou .zshrc ou qualquer outro), então ele é executado para cada shell interativo (dentro e fora da tela):

CDS_PREFIX="/var/run/screen/S-$USER"  # screen uses this already
#CDS_PREFIX="/dev/shm/screen-$USER" # if /var/run isn't on tmpfs
# $STY = a string unique to the screen session
if [[ $STY ]]; then
        CDS_DIR="$CDS_PREFIX/dirs.$STY"
        unset CDS_PREFIX

        [[ -d $CDS_DIR ]] || mkdir -m 700 -p "$CDS_DIR"

        # old cmd-every-prompt design: avoids breakage if you run interactive bash from bash, then exit
        # Also, use this on systems without a /proc/<pid>/cwd
        #PROMPT_COMMAND='[[ $WINDOW ]] && ln -sf "$PWD" "$CDS_DIR/$WINDOW"'

        ln -sTf "/proc/$$/cwd" "$CDS_DIR/$WINDOW"       # -T saves a stat call
        cds() { cd -P "$CDS_DIR/$@"; }
else
        # CDS_DIR=( "$CDS_PREFIX"/dirs.* )  # cds will use the first array element
        cds() { cd -P "$CDS_PREFIX/"dirs.*/"$@"; }  # even support shells started before screen.  cd with multiple args takes the first one without complaint.
fi

Assim, você pode abrir uma nova janela de tela e cds 5 levará você ao cwd do shell na janela 5.

Isso funciona mesmo para shells iniciados FORA da tela, e mesmo antes da sessão de tela existir. (já que, nesse caso, a expansão glob ocorre no tempo de execução de cds , em vez de quando foi definida como com o hack de array-variable que comentei, já que é pior em todos os aspectos.)

Sobrecarga total:

  • em todas as inicializações do shell interativo:
    • 8 linhas de código sem comentário para analisar.
    • uma estatística
    • a ln -sTf para um diretório no tmpfs
  • Sobrecarga de memória contínua após o início do shell:
    • 1 shell var e 1 pequena função
    • sem ambiente vars
  • armazenamento:
    • um diretório de um link simbólico por janela de tela (não é removido depois que o windows fecha)
  • por comando:
    • nenhum

Sem cd -P , o \w no seu $PS1 expandiria para /proc/3069/cwd , em vez do caminho canônico (links simbólicos seguidos) obtido com -P .

A versão que usa PROMPT_COMMAND pode modificar cds() para cd para levá-lo ao diretório lógico. (Armazene o CWD como texto em um arquivo, em vez de um link simbólico. pwd > "$CDS_DIR/$WINDOW" é apenas um shell embutido, portanto menos sobrecarga do que fork / execução de um binário. Também economiza o trabalho de contornar o GNU readlink ausente em alguns Sistemas Linux.) Isso seria útil se você trabalha frequentemente em links simbólicos para diretórios, onde pwd -P (e /bin/pwd ) não é o mesmo que pwd .

Você pode substituir as funções cd , pushd e popd por funções que atualizam o symlink, em vez de fazer isso em todos os prompts. Com essa configuração, o uso interativo de coisas como (cd foo; command there) enganará sua configuração, porque o cd que é executado no subshell atualizará o symlink, mas sem modificar o pwd do processo principal do shell.

Ok, aqui está a "outra versão", que conecta cd , pushd e popd e levará você ao mesmo diretório lógico que seu shell em qualquer janela de tela:

# Use this version on systems without '/proc/<pid>/cwd', or for logical directories (non-dereferencing of symlinks).

CDS_PREFIX="/var/run/screen/S-$USER"
#CDS_PREFIX="/dev/shm/screen-$USER"
if [[ $STY ]]; then
    CDS_DIR="$CDS_PREFIX/dirs.$STY"
    unset CDS_PREFIX
    [[ -d $CDS_DIR ]] || mkdir -m 700 -p "$CDS_DIR"

    function cd    () { command cd    "$@"; pwd > "$CDS_DIR/$WINDOW"; }
    function pushd () { command pushd "$@"; pwd > "$CDS_DIR/$WINDOW"; }
    function popd  () { command popd  "$@"; pwd > "$CDS_DIR/$WINDOW"; }
    #PROMPT_COMMAND='[[ $WINDOW ]] && pwd > "$CDS_DIR/$WINDOW"'
    if [[ -e "$CDS_DIR/$WINDOW" && ! -f "$CDS_DIR/$WINDOW" ]]; then
        rm -f "$CDS_DIR/$WINDOW"  # could exist if switching from symlink-to-dir style
    fi
    cd .

#   cds() { local d="$(<"$CDS_DIR/$1")"; shift; cd "$d" "$@"; }
    cds() { cd "$(<"$CDS_DIR/$1")"; }
else
    # CDS_DIR=( "$CDS_PREFIX"/dirs.* )  # cds will use the first array element
    cds() { cd "$(<"$CDS_PREFIX/"dirs.*/"$1")"; }  # even support shells started before screen.
fi

Sobrecarga: um open(2) e write(2) para tmpfs para cada cd , pushd e popd que você digitar ou colar. Caso contrário, o mesmo. Ainda não vai doer, em qualquer sistema poderoso o suficiente para executar bash e screen em primeiro lugar. :)

Acredite no link para ter a ideia de criar um CD. Eu gosto muito melhor do que PROMPT_COMMAND . Descobri que, enquanto procurava para ver se alguém havia inventado isso, e se eu deveria postar aqui ou no link .

Eu usei alguns bash-isms (como [[ ]] ) porque acho que o zsh também os suporta, e esperamos que ninguém esteja usando o POSIX sh como seu shell interativo.

    
por 06.02.2015 / 16:07