¿Incluir comando en el archivo de salida?


17

Perdón por el título confuso!

Supongamos que corro

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

Obtendré un archivo llamado "kwin-dependen" en mi carpeta de escritorio.

¿Hay algún truco para incluir el comando que emití como parte del archivo, preferiblemente al comienzo del archivo?

Entonces, al menos en 14.04 LTS, las primeras líneas se verían así:

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

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

En lugar de simplemente así:

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

3
Como ahora hay muchas otras soluciones buenas y flexibles, tal vez debería considerar no aceptar la respuesta que sugiere escribir manualmente el comando en el archivo al escribirlo dos veces y aceptar una de las soluciones versátiles.
Byte Commander

Respuestas:


18

Simplemente usaría una función simple. Agregue esto a su ~/.bashrcarchivo:

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

Ahora, cada vez que desee ejecutar un comando e imprimirlo, puede hacer lo siguiente:

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

Lo anterior produce este archivo:

$ 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

No me refiero a mover los postes de meta aquí, pero ¿hay alguna manera de que su código también acepte alias? Por ejemplo, si el alias apt-cache dependsa acd, me sale "No comando 'ACD' encontró, quiso decir: ..." cuando corro runcom acd leafpad > out.
DK Bose

Los alias @DKBose se definen en el archivo .bashrc, no en el shell, y las funciones llaman solo a los archivos binarios que se encuentran en la variable $ PATH. Pero puedes hacer un simple truco. Por ejemplo, lstiene un alias ls --color=auto' en la realidad. Lo que podría hacer (siempre y cuando no hay comillas simples o dobles en su alias), es la siguiente: $ terdonsFunction $(alias ls | awk -F '=' '{$1="";print}'| tr "'" " ") .
Sergiy Kolodyazhnyy

O convierta su comando en una variable. Como mostré en mi respuesta antes. MYCOMMAND="apt-cache depends"; terdonsFunction $MYCOMMAND leafpad > out.txt
Sergiy Kolodyazhnyy

@Serg, consulte la respuesta de GARCIN David: askubuntu.com/a/688936/248158
DK Bose

Esta es la respuesta "obvia" y funciona muy bien a menos que alguno de los argumentos implique código que se ejecute y tenga efectos secundarios que podrían acumularse. Este es un caso extremo, por lo que no ocurriría muy a menudo.
Joe

11

Tu puedes hacer:

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

Lo mismo usando echocadenas en lugar de Aquí ( <<<):

echo 'apt-cache depends kde-window-manager' | tee file.txt | bash >>file.txt
  • tee escribirá en STDOUT y también en el archivo file.txt

  • El STDOUT de teeie apt-cache depends kde-window-managerserá alimentado bashpara ejecutar el comando y agregar el STDOUT a file.txt.

Ejemplo:

$ 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>

1
¡Gran respuesta! Simple y al grano! Estaba probando uno teepero el mío seguía fallando. ¡Buen trabajo! +1
Terrance

@Seth También he pensado en jugar con los descriptores de archivo, pero teeparece ordenado :)
heemayl

11

Lo más minimalista: enfoque # 4 y # 3, ambos podrían convertirse en función; # 2 mi favorito - awk. # 1 usa el scriptcomando: herramienta muy versátil, útil para grabar líneas de comando en general; aplicable en cualquier lugar, para lo que quiera grabar.

Enfoque n. ° 1: hay un /usr/bin/scriptcomando (que viene con ubuntu por defecto) para grabar la salida de la línea de comandos, que captura todo, junto con el indicador y el comando. Para guardar un comando y su salida en un archivo específico, use el -cindicador y especifique el archivo de salida. Ejemplo

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 20151022 星期四 085846
gnome-terminal
  Depends: gconf-service
    gconf-service:i386
  Depends: libatk1.0-0
  Depends: libc6
  Depends: libgconf-2-4
  (extra output omitted)

Script done on 20151022 星期四 085846

Enfoque # 2: hacker de awk

Awk tiene una system()función que le permite ejecutar comandos de shell desde awkscript o comando . La salida se mostrará en la pantalla, primero el comando, luego la salida. Para redirigir lo que ve a un archivo, utilice el >operador.

Eso se puede hacer de dos maneras: solicite al usuario que ingrese cosas desde stdin o como argumento de línea de comando. El primero es más fácil de lograr, por lo tanto, publicar eso.

(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) Versión de línea de comando args; sin incluir la salida para evitar responder demasiado tiempo. Nuevamente, agregue >para redirigir al archivo

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

Enfoque n. ° 3: pídale a bash que haga el trabajo por usted

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

Redireccionar a archivo con >operador:

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

Enfoque n. ° 4: (mi segundo favorito)

Inspirado en la publicación de ByteCommander; podemos usar ready luego ejecutar los comandos necesarios en subshell

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

Ejecución de muestra:

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

Enfoque # 5:

Use echoo here string(aka <<< "string") para proporcionar argumentos a sh -ctravés dexargs

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

Y si quieres, puedes usar este mismo truco con un 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 {}; {}"'

Agradable, pero no incluye el comando como lo hace el código de Arronical.
DK Bose

@DKBose Agregaré otro enfoque que incluirá el comando. Cinco minutos
Sergiy Kolodyazhnyy

@DKBose ¿cómo es mi enfoque # 2?
Sergiy Kolodyazhnyy

Eso es inteligente, awkrealmente es un chico muy configurable, ¿no? `script se ve útil para algunos otros usos también.
Arronical

1
Esta es la mejor respuesta porque el uso de secuencias de comandos evita los efectos secundarios de los argumentos que podrían ejecutar código cuando se muestran con eco, etc., lo que hace que la segunda ejecución prevista tenga resultados diferentes que si el comando se ejecutara por separado.
Joe

6
  1. comienzo script -q outputfile
  2. Ejecute su comando
  3. Presione Ctrl-D
  4. Abre el archivo outputfile

Ejemplo

comienzo script

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

Comience su comando

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

Presione Ctrl-D

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

Muestra tu comando y salida

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

y verás algo como esto

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

5

Si desea expansión de alias (solo bash) puede hacerlo de esta manera:

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

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

    shift #skip 1st arg

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

Ahora puedes correr

runcmd acd leafpad > out

4

Puede haber una manera más fácil, pero puede hacerlo mediante un script:

#!/bin/sh
echo $1
apt-cache depends $1

Cree un archivo scriptcon este contenido en su carpeta Inicio y otorgue permiso de ejecución

chmod +x script

Ejecútelo de esta manera:

./script kde-window-manager > ~/Desktop/kwin-depends

¡Este enfoque tiene la ventaja de facilitar la repetición de esa línea de comando más adelante si lo desea! También puede escribir la redirección en el script, de modo que script.shsiempre cree un archivo llamado script.logcon su salida.
Gaurav

4

Solución extremadamente simple usando una función Bash de una línea

Preparación:

Este enfoque utiliza una función bash personalizada para proporcionar la funcionalidad deseada. Lo define ejecutando la siguiente línea en su sesión de terminal. tenga en cuenta que puede elegir cualquier nombre de variable bash válido en lugar de runandlog:

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

Sin embargo, esto solo persiste durante la sesión de Bash actual, es decir, después de cerrar la ventana del terminal, la función desaparecerá.
Sin embargo, si lo intentó y le gustó, puede hacerlo siempre editando su ~/.bashrcarchivo y agregando esta línea al final.

Cómo utilizar:

Después de haber definido la función, puede usarla para ejecutar comandos mientras registra tanto el comando en sí como su salida en un archivo. Incluso podría agregar más información como el usuario que lo ejecutó, que ya incluí en la función, o la hora exacta en que se ejecutó. ¡Las solicitudes de características en los comentarios son bienvenidas! :)

La sintaxis es simple:

runandlog LOGFILENAME YOUR-COMMAND-WITH-ARGUMENTS

Ejemplo:

Un ejemplo de sesión como usuario bytecommander, que opera desde el directorio de inicio podría verse así:

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

Lo que dará como resultado un nuevo archivo mylogfile (si ya existe, la función agregará la salida a él) en el directorio actual con el contenido:

[bytecommander] $ fortune 
A mathematician is a device for turning coffee into theorems.
        -- P. Erdos

3

Un truco bastante poco inteligente pero funcional sería:

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

Feo, pero funciona!


Estoy aceptando esta respuesta porque la solución es más ampliamente aplicable.
DK Bose

@DKBose Tendrá que escribir el módulo dos veces. Pero la solución con un script es realmente universal.
Piloto6

Lamento tener que aceptar esta respuesta aunque haga lo que pedí. ¡Espero que no te moleste!
DK Bose

2
No es un problema @DKBose, sabía que era una solución bastante poco elegante cuando envié la respuesta, y he aprendido algunas cosas buenas de las respuestas alternativas publicadas.
Arronical

2

Simplemente puede pasar el comando a una función que imprimirá primero el comando y luego la salida del comando (las redirecciones se mantienen fuera del comando impreso intencionalmente, puede cambiar esto fácilmente eliminando las comillas del comando e imprimiendo y ejecutando en su $@lugar de $1en la función):

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

bar

Para agregar el comando después, puede ejecutar este comando, que insertará el último comando ejecutado en la parte superior de un archivo:

<<<"$(<foo)" cat <(history 2 | sed -n '1s/  [0-9][0-9]*  \(.*\)/\1\n/p') - >foo
  • <<<"[...]": aquí cadena; [...]se redirige a cat's stdin;
  • $(<foo): sustitución de comando; se reemplaza con el contenido de "foo";
  • cat [...] - >foo: Concatena stdina [...]y salidas a "foo";
  • <([...]): sustitución del proceso: se reemplaza con un descriptor de archivo que contiene la salida de [...];
  • history 2 | sed -n '1s/ [0-9][0-9]* \(.*\)/\1\n/p': genera los dos últimos comandos, elimina dos espacios seguidos de uno o más dígitos seguidos de dos espacios desde la primera línea y lo imprime;
$ printf "bar\n" >foo
$ <<<"$(<foo)" cat <(history 2 | sed -n '1s/  [0-9][0-9]*  \(.*\)/\1\n/p') - >foo
$ cat foo
printf "bar" >foo

bar

¿Por qué solo estás imprimiendo $1? Y no hay necesidad de hacerlo eval.
terdon

@terdon Bueno, la idea era mantener las redirecciones fuera del comando impreso, ya que pensé que esto podría haberse visto mejor en el caso de OP. No obstante, si lo cambio ahora, sería idéntico a su respuesta. Sin embargo, sí, evalno es necesario, no estoy seguro de por qué lo agregué antes. Gracias.
kos
Al usar nuestro sitio, usted reconoce que ha leído y comprende nuestra Política de Cookies y Política de Privacidad.
Licensed under cc by-sa 3.0 with attribution required.