Incluir comando no arquivo de saída?

17

Desculpe pelo título confuso!

Suponha que eu corra

apt-cache depends kde-window-manager > ~/Desktop/kwin-depends

Vou pegar um arquivo chamado "kwin-depends" na minha pasta Desktop.

Existe algum truque para incluir o comando que eu emiti como parte do arquivo, de preferência no início do arquivo?

Então, pelo menos em 14.04 LTS, as primeiras linhas ficariam assim:

apt-cache depends kde-window-manager > ~/Desktop/kwin-depends

kde-window-manager
  Depends: kde-runtime
  Depends: libc6
 |Depends: libegl1-mesa
  Depends: <libegl1-x11>

Em vez de apenas assim:

kde-window-manager
  Depends: kde-runtime
  Depends: libc6
 |Depends: libegl1-mesa
  Depends: <libegl1-x11>
    
por DK Bose 22.10.2015 / 16:18

9 respostas

19

Eu usaria apenas uma função simples. Adicione isto ao seu arquivo ~/.bashrc :

function runcom(){
    echo "$@"
    ## Run the command
    $@
}

Agora, sempre que você quiser executar um comando e imprimi-lo, você pode fazer:

runcom apt-cache depends kde-window-manager > out

O acima produz este arquivo:

$ cat out
apt-cache depends kde-window-manager
kde-window-manager
  Depends: perl
  Depends: kde-runtime
  Depends: kde-style-oxygen
  Depends: libc6
 |Depends: libegl1-mesa
  Depends: <libegl1-x11>
    libegl1-mesa
  Depends: libgcc1
 |Depends: libgl1-mesa-glx
  Depends: <libgl1>
    libgl1-mesa-swx11
    libgl1-mesa-glx
 |Depends: libgles2-mesa
  Depends: <libgles2>
    libgles2-mesa
  Depends: libice6
  Depends: libkactivities6
  Depends: libkcmutils4
  Depends: libkdeclarative5
  Depends: libkdecorations4abi2
  Depends: libkdecore5
  Depends: libkdeui5
  Depends: libkio5
  Depends: libknewstuff3-4
  Depends: libkwineffects1abi5
  Depends: libkwinglesutils1
  Depends: libkwinglutils1abi2
  Depends: libkworkspace4abi2
  Depends: libplasma3
  Depends: libqt4-dbus
  Depends: libqt4-declarative
  Depends: libqt4-script
  Depends: libqtcore4
  Depends: libqtgui4
  Depends: libsm6
  Depends: libstdc++6
  Depends: libwayland-client0
 |Depends: libwayland-egl1-mesa
  Depends: <libwayland-egl1>
    libwayland-egl1-mesa
  Depends: libx11-6
  Depends: libx11-xcb1
  Depends: libxcb-composite0
  Depends: libxcb-damage0
  Depends: libxcb-image0
  Depends: libxcb-keysyms1
  Depends: libxcb-randr0
  Depends: libxcb-render0
  Depends: libxcb-shape0
  Depends: libxcb-shm0
  Depends: libxcb-sync1
  Depends: libxcb-xfixes0
  Depends: libxcb-xtest0
  Depends: libxcb1
  Depends: libxcursor1
  Depends: libxext6
  Depends: libxrandr2
  Depends: libxxf86vm1
  Breaks: kde-style-bespin
  Breaks: kde-style-bespin:i386
  Breaks: <kde-style-skulpture>
  Breaks: <kde-style-skulpture:i386>
  Breaks: kde-workspace-data
  Breaks: <kde-workspace-data:i386>
  Breaks: kdeartwork-theme-window
  Breaks: kdeartwork-theme-window:i386
  Breaks: <kdebase-workspace-data>
  Breaks: <kdebase-workspace-data:i386>
  Breaks: kwin-style-crystal
  Breaks: kwin-style-crystal:i386
  Breaks: kwin-style-dekorator
  Breaks: kwin-style-dekorator:i386
  Breaks: kwin-style-qtcurve
  Breaks: kwin-style-qtcurve:i386
  Replaces: kde-workspace-data
  Replaces: <kde-workspace-data:i386>
  Replaces: <kdebase-workspace-data>
  Replaces: <kdebase-workspace-data:i386>
  Conflicts: kde-window-manager:i386
    
por terdon 23.10.2015 / 13:28
12

Você pode fazer:

tee file.txt <<<'apt-cache depends kde-window-manager' | bash >>file.txt

A mesma coisa que usa echo em vez de "Here strings" ( <<< ):

echo 'apt-cache depends kde-window-manager' | tee file.txt | bash >>file.txt
  • tee gravará no STDOUT e também no arquivo file.txt

  • O STDOUT de tee ou seja, apt-cache depends kde-window-manager será alimentado para bash para executar o comando e anexar o STDOUT a file.txt .

Exemplo:

$ echo 'apt-cache depends kde-window-manager' | tee file.txt | bash >>file.txt

$ cat file.txt 
apt-cache depends kde-window-manager
kde-window-manager
  Depends: kde-runtime
  Depends: libc6
 |Depends: libegl1-mesa
  Depends: <libegl1-x11>
    
por heemayl 22.10.2015 / 20:28
11

A maioria dos minimalistas - abordagem # 4 e # 3, ambos podem ser convertidos em função; # 2 meu favorito - awk . # 1 usa o comando script - ferramenta muito versátil, útil para gravar linhas de comando em geral; aplicável em qualquer lugar, para o que você quiser gravar.

Abordagem # 1: Existe um comando /usr/bin/script (que vem com o ubuntu por padrão) para gravar a saída da linha de comando, que captura tudo, junto com o prompt e o comando. Para salvar apenas um comando e sua saída em um arquivo específico, use -c flag e especifique o arquivo de saída. Exemplo

xieerqi:$ script -c 'apt-cache depends gnome-terminal' outputFile.txt
Script started, file is outputFile.txt
gnome-terminal
  Depends: gconf-service
    gconf-service:i386
  Depends: libatk1.0-0
  Depends: libc6
  Depends: libgconf-2-4
  Depends: libgdk-pixbuf2.0-0
     (extra output omitted)
Script done, file is outputFile.txt

xieerqi:$ cat outputFile.txt                                              
Script started on 2015年10月22日 星期四 08时58分46秒
gnome-terminal
  Depends: gconf-service
    gconf-service:i386
  Depends: libatk1.0-0
  Depends: libc6
  Depends: libgconf-2-4
  (extra output omitted)

Script done on 2015年10月22日 星期四 08时58分46秒

Abordagem # 2: hackware do awk

O awk tem a função system() , que permite executar comandos do shell em awk script ou comando . A saída aparecerá na tela, comando primeiro, saída próxima. Para redirecionar o que você vê para um arquivo use o operador > .

Isso pode ser feito de duas maneiras - peça ao usuário para inserir informações de stdin ou como argumento de linha de comando. Primeiro é mais fácil de conseguir, portanto postando isso.

(1) awk 'BEGIN{ print "Enter command to run: "; getline com < "/dev/stdin"; system(com) }'

 awk 'BEGIN{ print "Enter command to run: "; getline com < "/dev/stdin"; system(com) }'
Enter command to run: 
apt-cache depends gnome-terminal
gnome-terminal
  Depends: gconf-service
    gconf-service:i386
  Depends: libatk1.0-0
  Depends: libc6
  Depends: libgconf-2-4
  Depends: libgdk-pixbuf2.0-0
  Depends: libglib2.0-0 
  (extra output omitted)

(2) Versão dos argumentos da linha de comando; não incluindo saída para evitar que a resposta seja longa demais. Novamente, acrescente > para redirecionar para o arquivo

awk 'BEGIN{for (i=1; i<= ARGC; i++) myString = myString"  "ARGV[i]; print myString; system(myString)  }' apt-cache depends gnome-terminal

Abordagem # 3: peça ajuda para fazer o trabalho para você

xieerqi@eagle:~$ bash -c ' MYCOMMAND="apt-cache depends gnome-terminal"; echo $MYCOMMAND ; $MYCOMMAND    '
apt-cache depends gnome-terminal
gnome-terminal
  Depends: gconf-service
    gconf-service:i386
  Depends: libatk1.0-0
  Depends: libc6
  Depends: libgconf-2-4
  Depends: libgdk-pixbuf2.0-0
  Depends: libglib2.0-0

Redirecionar para o arquivo com > operator:

bash -c ' MYCOMMAND="apt-cache depends gnome-terminal"; echo $MYCOMMAND ; $MYCOMMAND ' > output.txt

Abordagem # 4: (meu segundo favorito)

Inspirado na postagem de ByteCommander; podemos usar read e depois executar os comandos necessários em subshell

read command && (printf "COMMAND: %s" "$command";printf "\n+++++++\n"; sh -c "$command")

Execução da amostra:

xieerqi:$ read command && (printf "COMMAND READ: %s" "$command";printf "\n+++++++\nOUTPUT\n"; sh -c "$command")                                       
printf "This was a triumph; I'm making a note here - huge success"
COMMAND READ: printf "This was a triumph; I'm making a note here - huge success"
+++++++
OUTPUT
This was a triumph; I'm making a note here - huge success

Abordagem # 5:

Use echo ou here string (também conhecido como <<< "string" ) para fornecer argumentos para sh -c a xargs

xieerqi:$ echo "apt-cache policy gnome-terminal" | xargs -I {} bash -c 'echo {}; {}'                                                            
apt-cache policy gnome-terminal
gnome-terminal:
  Installed: 3.6.2-0ubuntu1
  Candidate: 3.6.2-0ubuntu1
  Version table:
 *** 3.6.2-0ubuntu1 0
        500 http://us.archive.ubuntu.com/ubuntu/ trusty/main amd64 Packages
        100 /var/lib/dpkg/status

E, se quiser, você pode usar esse mesmo truque com um alias:

xieerqi:$ printAndRun <<< "apt-cache policy gnome-terminal"                                                                                     
apt-cache policy gnome-terminal
gnome-terminal:
  Installed: 3.6.2-0ubuntu1
  Candidate: 3.6.2-0ubuntu1
  Version table:
 *** 3.6.2-0ubuntu1 0
        500 http://us.archive.ubuntu.com/ubuntu/ trusty/main amd64 Packages
        100 /var/lib/dpkg/status

xieerqi:$ type printAndRun
printAndRun is an alias for 'xargs -I {} bash -c "echo {}; {}"'
    
por Sergiy Kolodyazhnyy 22.10.2015 / 16:59
6
  1. Iniciar script -q outputfile
  2. Execute seu comando
  3. Pressione Ctrl - D
  4. Abra o arquivo outputfile

Exemplo

Iniciar script

[aboettger:~/tmp] % script -q ~/Desktop/kwin-depends

Inicie seu comando

[aboettger:~/tmp] % apt-cache depends kde-window-manager
<kde-window-manager>
[aboettger:~/tmp] % 

Pressione Ctrl - D

Script done, file is /home/aboettger/Desktop/kwin-depends

Mostre seu comando e saída

[aboettger:~/tmp] % cat ~/Desktop/kwin-depends

e você verá algo parecido com isto

[aboettger:~/tmp] % apt-cache depends kde-window-manager
<kde-window-manager>
    
por A.B. 23.10.2015 / 13:29
5

Se você quiser expansão alias (bash somente), você pode fazer desta forma:

function runcmd
{
    local check_cmd=${BASH_ALIASES[]}

    if [ -z "$check_cmd" ]; then
        check_cmd=
    fi

    shift #skip 1st arg

    echo "$check_cmd $@"
    $check_cmd $@
}

Agora você pode executar

runcmd acd leafpad > out
    
por GARCIN David 23.10.2015 / 17:16
4

Pode ser mais fácil, mas você pode fazer isso por um script:

#!/bin/sh
echo 
apt-cache depends 

Crie um arquivo script com este conteúdo em sua pasta Pessoal e dê permissão de execução

chmod +x script

Execute desta forma:

./script kde-window-manager > ~/Desktop/kwin-depends
    
por Pilot6 22.10.2015 / 16:35
4

Solução extremamente simples usando uma função Bash de uma linha

Preparação:

Essa abordagem usa uma função bash personalizada para fornecer a funcionalidade desejada. Você define isso executando a seguinte linha na sua sessão de terminal. Observe que você pode escolher qualquer nome de variável bash válido em vez de runandlog :

runandlog () ( IFS=' '; printf "[%s] $ %s\n%s\n" "$USER" "${*:2}" "$("${@:2}")" | tee -a "" | tail -n +2; )

Isso, no entanto, só persiste para a sessão atual do Bash, o que significa que depois de fechar a janela do terminal, a função desaparecerá. Se você tentou e gostou, você pode disponibilizá-lo sempre editando o arquivo ~/.bashrc e acrescentando essa linha ao final.

Como usar:

Depois de definir a função, você pode usá-la para executar comandos enquanto registra o próprio comando e sua saída em um arquivo. Você pode até adicionar mais informações, como o usuário que a executou, que eu já incluí na função ou a hora exata em que foi executada. Recurso-pedidos nos comentários são bem-vindos! :)

A sintaxe é simples:

runandlog LOGFILENAME YOUR-COMMAND-WITH-ARGUMENTS

Exemplo:

Um exemplo de sessão como usuário bytecommander , operando a partir do diretório inicial, pode ter esta aparência:

bytecommander: ~ $  runandlog mylogfile fortune
A mathematician is a device for turning coffee into theorems.
        -- P. Erdos

O que resultará em um novo arquivo mylogfile (se já existir, a função anexará a saída a ele!) no diretório atual com o conteúdo:

[bytecommander] $ fortune 
A mathematician is a device for turning coffee into theorems.
        -- P. Erdos
    
por Byte Commander 22.10.2015 / 21:05
3

Um truque bastante desobstruído mas funcional seria:

(echo "apt-cache depends kde-window-manager" && apt-cache depends kde-window-manager) > ~/Desktop/kwin-depends

Feio, mas funciona!

    
por Arronical 22.10.2015 / 16:35
2

Você poderia simplesmente passar o comando para uma função que imprimirá o comando primeiro e a saída do comando depois (os redirecionamentos são mantidos fora do comando impresso intencionalmente, você pode facilmente alterar isso removendo as aspas do comando e imprimindo e executando $@ em vez de na função):

function myfunction() {
    printf "%s\n\n" ""
    
}
$ myfunction "printf \"bar\n\"" > foo
$ cat foo
printf "bar\n"

bar

Para adicionar o comando depois, você pode executar este comando, que irá inserir o último comando executado no topo de um arquivo:

<<<"$(<foo)" cat <(history 2 | sed -n '1s/  [0-9][0-9]*  \(.*\)/\n/p') - >foo
  • <<<"[...]" : aqui string; [...] é redirecionado para cat ' stdin ;
  • $(<foo) : substituição de comando; é substituído pelo conteúdo "foo";
  • cat [...] - >foo : concatena stdin para [...] e produz para "foo";
  • <([...]) : substituição do processo: é substituído por um descritor de arquivo contendo a saída de [...] ;
  • history 2 | sed -n '1s/ [0-9][0-9]* \(.*\)/\n/p' : gera os dois últimos comandos, remove dois espaços seguidos por um ou mais dígitos seguidos por dois espaços da primeira linha e imprime-os;
$ printf "bar\n" >foo
$ <<<"$(<foo)" cat <(history 2 | sed -n '1s/  [0-9][0-9]*  \(.*\)/\n/p') - >foo
$ cat foo
printf "bar" >foo

bar
    
por kos 22.10.2015 / 17:59