Eu gostaria de poder usar o resultado do último comando executado em um comando subsequente. Por exemplo,
$ find . -name foo.txt
./home/user/some/directory/foo.txt
Agora, digamos que eu queira abrir o arquivo em um editor ou excluí-lo ou fazer outra coisa com ele, por exemplo
mv <some-variable-that-contains-the-result> /some/new/location
Como eu posso fazer isso? Talvez usando alguma variável bash?
Atualizar:
Para esclarecer, não quero atribuir coisas manualmente. O que eu estou procurando é algo como variáveis bash embutidas, por exemplo
ls /tmp
cd $_
$_
mantém o último argumento do comando anterior. Eu quero algo semelhante, mas com a saída do último comando.
Atualização final:
A resposta de Seth funcionou muito bem. Algumas coisas a ter em mente:
- não se esqueça de
touch /tmp/x
experimentar a solução pela primeira vez - o resultado será armazenado apenas se o código de saída do último comando for bem-sucedido
linux
bash
command-line
armandino
fonte
fonte
Respostas:
Esta é uma solução realmente hacky, mas parece funcionar na maior parte do tempo. Durante o teste, notei que às vezes não funcionava muito bem ao obter uma ^Clinha de comando, embora eu a ajustava um pouco para me comportar um pouco melhor.
Esse hack é apenas um hack de modo interativo, e estou bastante confiante de que não o recomendaria a ninguém. É provável que os comandos em segundo plano causem um comportamento ainda menos definido que o normal. As outras respostas são uma maneira melhor de obter resultados programaticamente.
Dito isto, aqui está a "solução":
Defina essa variável de ambiente bash e emita comandos conforme desejado.
$LAST
normalmente terá a saída que você está procurando:fonte
PROMPT_COMMAND='last="$(cat /tmp/last)";lasterr="$(cat /tmp/lasterr)"; exec >/dev/tty; exec > >(tee /tmp/last); exec 2>/dev/tty; exec 2> >(tee /tmp/lasterr)'
que fornece ambos$last
e$lasterr
.No such file or directory
2> >(tee /tmp/lasterr 1>&2)
porque a saída padrão detee
deve ser redirecionada de volta ao erro padrão.Não conheço nenhuma variável que faça isso automaticamente . Para fazer algo além de copiar e colar o resultado, você pode executar novamente o que acabou de fazer, por exemplo
Onde
!!
está a expansão da história que significa 'o comando anterior'.Se você espera que exista um único nome de arquivo com espaços ou outros caracteres que possam impedir a análise adequada de argumentos, cite o resultado (
vim "$(!!)"
). Deixá-lo entre aspas permitirá que vários arquivos sejam abertos ao mesmo tempo, desde que não incluam espaços ou outros tokens de análise de shell.fonte
vim `!!`
date "+%N"
e depoisecho $(!!)
Bash é uma linguagem feia. Sim, você pode atribuir a saída à variável
Mas é melhor esperar que você tenhafind
retornado apenas um resultado e que esse resultado não tenha caracteres "ímpares", como retornos de carro ou feeds de linha, pois eles serão modificados silenciosamente quando atribuídos a uma variável Bash.Mas é melhor ter cuidado para citar sua variável corretamente ao usá-la!
É melhor agir diretamente no arquivo, por exemplo, com
find
's-execdir
(consulte o manual).ou
fonte
echo "${MY_VAR}"
para ver que é esse o caso.Existem mais de uma maneira de fazer isso. Uma maneira é usar a
v=$(command)
qual atribuirá a saída do comandov
. Por exemplo:E você também pode usar aspas.
No Guia para Iniciantes do Bash ,
EDIT: Após a edição da pergunta, parece que isso não é o que o OP está procurando. Até onde eu sei, não há variável especial como
$_
a saída do último comando.fonte
É bem fácil Use aspas:
E então você pode usar isso a qualquer momento no futuro
fonte
Disclamers:
Ao executar um shell interativo no tmux, você pode acessar facilmente os dados atualmente exibidos em um terminal. Vamos dar uma olhada em alguns comandos interessantes:
Sim, isso nos oferece muitas possibilidades agora :) Quanto a mim, montei um apelido simples:
alias L="tmux capture-pane; tmux showb -b 0 | tail -n 3 | head -n 1"
e agora toda vez que preciso acessar a última linha, simplesmente uso$(L)
para obtê-la.Isso é independente do fluxo de saída que o programa usa (seja stdin ou stderr), o método de impressão (ncurses etc.) e o código de saída do programa - os dados precisam apenas ser exibidos.
fonte
Eu acho que você pode ser capaz de hackear uma solução que envolve a configuração do shell para um script que contém:
Então, se você definir
$PROMPT_COMMAND
a saída de um delimitador, poderá escrever uma função auxiliar (talvez chamada_
) que obtenha o último bloco desse log, para que você possa usá-lo como:fonte
Você pode configurar o seguinte alias no seu perfil do bash:
Então, digitando 's' após um comando arbitrário, você pode salvar o resultado em uma variável do shell 'it'.
Assim, o exemplo de uso seria:
fonte
grab
função dessa linha cópias enésimo do último comando para clipboard gist.github.com/davidhq/f37ac87bc77f27c5027eAcabei de destilar essa
bash
função a partir das sugestões aqui:Então, você apenas faz:
Atualização : um usuário anônimo sugerido para substituir
echo
peloprintf '%s\n'
qual tem a vantagem de não processar opções como-e
no texto capturado. Portanto, se você espera ou experimenta essas peculiaridades, considere esta sugestão. Outra opção é usar em seucat <<<$grab
lugar.fonte
cat <<<$grab
opção?man bash
: "Here Strings: Uma variante dos documentos aqui, o formato é:<<<word
A palavra é expandida e fornecida ao comando em sua entrada padrão". Portanto, o valor de$grab
é alimentadocat
no stdin ecat
apenas o alimenta de volta ao stdout.Ao dizer "Gostaria de poder usar o resultado do último comando executado em um comando subseqüente", presumo - você quer dizer o resultado de qualquer comando, e não apenas encontrar.
Se for esse o caso - xargs é o que você está procurando.
find . -name foo.txt -print0 | xargs -0 -I{} mv {} /some/new/location/{}
OU se você estiver interessado em ver a saída primeiro:
find . -name foo.txt -print0
!! | xargs -0 -I{} mv {} /some/new/location/{}
Este comando lida com vários arquivos e funciona como um encanto, mesmo que o caminho e / ou o nome do arquivo contenham espaço (s).
Observe a parte mv {} / some / new / location / {} do comando. Este comando é construído e executado para cada linha impressa pelo comando anterior. Aqui a linha impressa pelo comando anterior é substituída no lugar de {} .
Trecho da página de manual do xargs:
Para mais detalhes, consulte a página do manual:
man xargs
fonte
Capture a saída com backticks:
fonte
Eu costumo fazer o que os outros aqui sugeriram ... sem a atribuição:
Você pode ficar mais chique se quiser:
fonte
Se tudo o que você deseja é executar novamente o seu último comando e obter a saída, uma variável bash simples funcionaria:
Então você pode executar seu comando na saída com:
Isso irá gerar um novo processo e executar novamente o seu comando, fornecendo a saída. Parece que o que você realmente gostaria seria um arquivo de histórico do bash para saída do comando. Isso significa que você precisará capturar a saída que o bash envia para o seu terminal. Você pode escrever algo para observar o / dev ou / proc necessário, mas isso é confuso. Você também pode criar um "canal especial" entre o seu termo e o bash com um comando tee no meio, que redireciona para o seu arquivo de saída.
Mas essas duas são soluções hacky. Eu acho que a melhor coisa seria o terminator, que é um terminal mais moderno com registro de saída. Basta verificar seu arquivo de log para obter os resultados do último comando. Uma variável bash semelhante à anterior tornaria isso ainda mais simples.
fonte
Aqui está uma maneira de fazer isso depois de executar seu comando e decidir que você deseja armazenar o resultado em uma variável:
Ou, se você souber antecipadamente que deseja o resultado em uma variável, poderá usar backticks:
fonte
Como alternativa às respostas existentes: Use
while
se os nomes dos arquivos puderem conter espaços em branco como este:Como escrevi, a diferença é relevante apenas se você precisar de espaços em branco nos nomes dos arquivos.
Nota: o único material incorporado não é sobre a saída, mas sobre o status do último comando.
fonte
você pode usar !!: 1. Exemplo:
fonte
Eu tinha uma necessidade semelhante, na qual queria usar a saída do último comando no próximo. Muito parecido com um | (tubo). por exemplo
para algo como -
Solução: criou este canal personalizado. Realmente simples, usando xargs -
Basicamente, nada criando uma mão curta para xargs, funciona como charme e é realmente útil. Acabei de adicionar o alias no arquivo .bash_profile.
fonte
Isso pode ser feito usando a mágica dos descritores de arquivos e a
lastpipe
opção shell.Isso deve ser feito com um script - a opção "lastpipe" não funcionará no modo interativo.
Aqui está o script que eu testei:
O que estou fazendo aqui é:
definindo a opção shell
shopt -s lastpipe
. Não funcionará sem isso, pois você perderá o descritor de arquivo.certificando-se de que meu stderr também seja capturado com
2>&1
canalizando a saída em uma função para que o descritor de arquivo stdin possa ser referenciado.
definindo a variável obtendo o conteúdo do
/proc/self/fd/0
descritor de arquivo, que é stdin.Estou usando isso para capturar erros em um script, portanto, se houver um problema com um comando, posso parar de processar o script e sair imediatamente.
Dessa forma, posso adicionar
2>&1 | exit_tests ; [[ "${PIPESTATUS[0]}" == "0" ]] || error_msg
por trás de cada comando que gostaria de verificar.Agora você pode apreciar sua produção!
fonte
Esta não é estritamente uma solução bash, mas você pode usar o piping com sed para obter a última linha de saída dos comandos anteriores.
Primeiro vamos ver o que tenho na pasta "a"
Então, seu exemplo com ls e cd se tornaria sed & piping em algo assim:
Portanto, a mágica real acontece com o sed, você canaliza o que sempre sai do que já foi mandado para o sed e sed imprime a última linha que você pode usar como parâmetro com back ticks. Ou você pode combinar isso com xargs também. ("man xargs" com casca é seu amigo)
fonte
O shell não possui símbolos especiais do tipo perl que armazenam o resultado do eco do último comando.
Aprenda a usar o símbolo de tubo com awk.
No exemplo acima, você pode fazer:
fonte
é ainda outra maneira, ainda que suja.
fonte
Acho que lembrar de canalizar a saída dos meus comandos em um arquivo específico é um pouco chato, minha solução é uma função na minha
.bash_profile
que captura a saída em um arquivo e retorna o resultado quando você precisar.A vantagem deste é que você não precisa executar novamente o comando inteiro (ao usar
find
ou outros comandos de execução longa que podem ser críticos)Simples o suficiente, cole isso no seu
.bash_profile
:Roteiro
Uso
Neste ponto, costumo adicionar apenas
| catch
ao final de todos os meus comandos, porque não há custo para fazê-lo e isso me poupa de ter que executar novamente os comandos que demoram muito tempo para serem finalizados.Além disso, se você deseja abrir a saída do arquivo em um editor de texto, você pode fazer isso:
fonte