Como executo vários comandos usando o mesmo argumento?

16

Gostaria de saber se é possível fazer ações em cadeia no terminal Ubuntu como:

action 1 on objectA . then action 2 on objectA 

sem ter que repetir o nome do objetoA mais.

Exemplo:

touch file.js && openEditor "$1" 

ou algo assim.

HoCo_
fonte
Há muitas maneiras de fazer isso, mas depende de suas necessidades. O que é o objetoA? um arquivo ? De que ações estamos falando?
Sergiy Kolodyazhnyy
obrigado, geralmente um arquivo de forma eficaz, também pode ser uma pasta
HoCo_
3
Aqui, &o comando "touch" será enviado em segundo plano. Se você pretendia "abrir o editor se toque bem-sucedido", então você quer &&em vez
Glenn Jackman
Por que você está colidindo com este post? Você já tem muitas respostas e até aceitou uma.
muru

Respostas:

27

Com o bash History Expansion , você pode consultar a enésima palavra da linha de comando atual usando, !#:npor exemplo,

$ touch foobar && ls -l !#:1
touch foobar && ls -l foobar
-rw-rw---- 1 steeldriver steeldriver 0 Jun 20 14:54 foobar

$ touch foo bar && ls -l !#:2
touch foo bar && ls -l bar
-rw-rw-r-- 1 steeldriver steeldriver 12 Jun 20 14:58 bar
chave de aço
fonte
Posso perguntar qual versão do bash você está usando?
Sergiy Kolodyazhnyy
@SergiyKolodyazhnyy this isGNU bash, version 4.3.48(1)-release
steeldriver
5
você também pode designar uma série de palavras :touch foo bar && ls -l !#:1-2
glenn jackman 20/18
11
@HoCo_ os !introduz caracteres uma expressão de expansão história quando você está em um shell interativo - que está destinado para a manipulação de linha de comando on-the-fly como você está digitando, e é script não-interativo desativado dentro
steeldriver
11
@HoCo_ em um script você deve saber o que o argumento é antes do tempo - assim, por exemplo, você poderia apenas fazerarg1=file.js; touch "$arg1" && openEditor "$arg1"
steeldriver
12

Há um atalho útil para um caso de uso comum. No seu exemplo, você está fazendo:

$ touch file.js
$ openEditor <alt>+<.>

No segundo comando, o truque é escrever openEditor(com um espaço depois) seguido de Alt+ .. Isto irá inserir o último argumento do último comando, que é file.js. (Se não funcionar Altpor algum motivo, também Escdeve funcionar.)

Como frequentemente o "objeto" é realmente o último argumento do comando anterior, isso pode ser usado com freqüência. É fácil de lembrar e se integrará rapidamente ao seu conjunto de atalhos de shell usados ​​intuitivamente.

Há várias coisas que você pode fazer com isso. Aqui está um artigo detalhado sobre as possibilidades: /programming/4009412/how-to-use-arguments-from-previous-command .

Como um bônus, isso funcionará não apenas no bash, mas em todos os programas que usam libreadline para processar a entrada da linha de comando.

Sebastian Stark
fonte
2
Você pode combinar isso com um argumento dígitos , por exemplo, para obter o segundo espera argumento Alte pressione 2.(ou Esc, 2, Esc, .), para obter o segundo ao último argumento de imprensa Alt+ -, tipo 2e pressionar Alt+ .(ou Esc, -2, Esc, .).
dessert
@dessert E se eu correr quiser mais de um dos argumentos? Por exemplo, eu correr echo 1 2 3 4, então eu quero 2e 3para o próximo comando
wjandrea
@dessert Encontrei eu mesmo! Você só precisa digitar outra coisa entre eles, como um espaço. Para concatená-los, a maneira mais fácil é digitar um espaço e depois retroceder.
Wjandrea
11
@wjandrea espera Alte tipo 2., pressione a barra de espaço, espera Alte tipo 3.- se você quiser um intervalo, a expansão histórico de uso: !!:2-3.
Sobremesa
9

No que diz respeito ao shell interativo padrão bashe ao shell de script dash, você pode usar $_para recuperar o último argumento do último comando .

$ echo "Hello World"; echo same "$_"
Hello World
same Hello World

csh e tcsh têm referências de histórico, especificamente para a última palavra do comando, você pode usar !$e para argumentos individuais - !:<index>:

~% echo foo bar
foo bar
~% echo !$
echo bar
bar

% echo bar baz
bar baz
% echo !:1
echo bar
bar

Em geral, é melhor atribuir o que quer que seja objectAa uma variável e usá-lo em vários comandos, loops etc. Como alternativa, uma função pode ser uma opção:

$ foo(){ echo "$@"; stat --print="%F\n" "$@";}
$ foo testdir
testdir
directory
Sergiy Kolodyazhnyy
fonte
11
Gostaria apenas de salientar que $_funciona de maneira um pouco diferente do que !#:nquando o último é expandido antes de salvar o comando no histórico. Então, voltar ao histórico ainda mostraria o comando com $_while !#:nteria sido substituído por seu valor real. Ambos têm seus prós e contras.
Dan
3
Além disso, como sempre, $_deve ser citado; caso contrário, ele será dividido e globulado como tudo o resto. (Nós simplesmente não o vemos aqui, pois echoune seus argumentos a um único espaço.) Mas, por exemplo touch "hello there"; ls -l $_ , não funciona.
precisa saber é o seguinte
11
@ Dan Eu acho que o maior profissional $_é que é portátil. Afinal, !#:né específico do bash.
26818 Sergiy Kolodyazhnyy
3

Eu recomendaria contra a abordagem da história dada na resposta da steeldriver . Isso depende do estado global, que é sempre frágil.

Melhor é fazer um loop inicial de todos os comandos necessários, usando uma variável adequada:

$ for c in touch gedit; do $c foo.txt; done

O que é um pouco problemático em geral é que o Bash não aborta quando há uma falha, ou seja, isso realmente se comporta como em touch foo.txt; gedit foo.txtvez de encadear &&. Portanto, para estar seguro, você pode adicionar um break:

$ for c in touch gedit; do $c foo.txt || break; done
leftaroundabout
fonte
1

Ao preparar uma linha, às vezes atribuo minha coisa repetida a uma variável de shell que uso várias vezes no comando. Lembro-me e editá-lo para usar um argumento diferente com seta para cima, controle + a, controle + seta para a direita para aproximar o cursor do t=.

t=testloop; asm-link -d "$t.asm" && perf stat -r2 ./"$t"

Observe que isso facilita a aderência a uma extensão ou uma variação no nome.

Observe também que preciso de uma ;atribuição após a variável, porque var=value cmdapenas define isso como uma variável de ambiente para esse comando e não afeta o contexto do shell.

Peter Cordes
fonte