Como executar um comando com um diretório como argumento e, em seguida, cd para o mesmo? Eu recebo "nenhum tal arquivo ou diretório"

15

Eu gostaria de construir uma função curta para fazer o seguinte. Digamos que eu mova o arquivo 'file.tex' para o diretório de documentos:

mv file.tex ~/Documents

Então, eu gostaria de cd para esse diretório:

cd ~/Documents

Gostaria de generalizar isso para qualquer diretório, para que eu possa fazer isso:

mv file.tex ~/Documents
follow

e tenha o comando follow lendo o destino do comando anterior e, em seguida, execute de acordo. Para um diretório simples, isso não economiza muito tempo, mas ao trabalhar com diretórios aninhados, seria tremendo ser capaz de usar apenas

mv file.tex ~/Documents/folder1/subfolder1
follow

Eu pensei que seria relativamente simples e que eu poderia fazer algo assim:

follow()
{
    place='history 2 | sed -n '1p;1q' | rev | cut -d ' ' -f1 | rev'
    cd $place
}

mas isso não parece funcionar. Se eu echo $place , eu obtenho a string desejada (estou testando com ~/Documents ), mas o último comando retorna

No such file or directory

O diretório certamente existe. Eu estou em uma perda. Você poderia me ajudar?

    
por Fire 15.08.2016 / 15:20

3 respostas

18

Em vez de definir uma função, você pode usar a variável $_ , que é expandida para o último argumento do comando anterior por bash . Então use:

cd "$_"

após o comando mv .

Você também pode usar a expansão do histórico:

cd !:$

Se você precisar usar uma função:

follow () { cd "$_" ;}
$ follow () { cd "$_" ;}
$ mv foo.sh 'foo bar'
$ follow 
foo bar$ 

N.B: Esta resposta é direcionada para o formato exato de argumentos da linha de comando que você usou quando estamos lidando com parâmetros posicionais. Para outros formatos, por ex. mv -t foo bar.txt , você precisa incorporar as verificações específicas de antemão, um invólucro seria apropriado.

    
por 15.08.2016 / 15:26
14

Com atalhos de teclado padrão, a combinação Alt . copia o último argumento da linha de comando anterior para o atual. Então, digitando

$ mv foo ~/some/long/path/
$ cd <Alt><.>

renderia

$ mv foo ~/some/long/path/
$ cd ~/some/long/path/

e seria ainda menos digitação do que a palavra follow .

Para maior comodidade, a repetição da combinação Alt . irá percorrer os últimos argumentos de todas as linhas de comando anteriores.

Adendo: O nome do comando bash correspondente a essa combinação de chaves é yank-last-arg ou insert-last-argument . Pode ser encontrado no bash manpage sob "Comandos para Manipular a História" ou no mais exaustivo Bash Reference Manual .)

    
por 15.08.2016 / 16:01
6

Você quase certamente está enfrentando o problema de que a expansão do til ocorre antes da expansão do parâmetro, o que pode ser explicado por um exemplo sucinto:

$ cd ~kaz
kaz $ var='~kaz'
kaz $ echo $var
~kaz
kaz $ cd $kaz
bash: cd: ~kaz: No such file or directory

Isso pode ser resolvido com eval . De qualquer forma, você vai precisar de eval , porque você está puxando comandos do histórico e eles podem conter expansões arbitrárias, como:

$ mv file.tex ~/Documents/$(compute_folder_name foo-param)/subfolder1
$ follow

(Existem problemas, como a reexpansão desses valores, que podem não corresponder mais à expansão original que ocorreu. Suponha que compute_folder_name seja uma função que incrementa alguma variável global.)

    
por 15.08.2016 / 18:02