Includi comando nel file di output?


17

Ci scusiamo per il titolo confuso!

Supponiamo che io corra

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

Prenderò un file chiamato "kwin-dipende" nella mia cartella Desktop.

C'è qualche trucco per includere il comando che ho emesso come parte del file, preferibilmente all'inizio del file?

Quindi, almeno in 14.04 LTS, le prime poche righe apparirebbero così:

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

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

Invece di così:

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

3
Poiché ora ci sono molte altre soluzioni valide e flessibili, dovresti forse considerare di non accettare la risposta che suggerisce di scrivere manualmente il comando nel file digitandolo due volte e accettando invece una delle soluzioni versatili.
Byte Commander

Risposte:


18

Vorrei solo usare una funzione semplice. Aggiungi questo al tuo ~/.bashrcfile:

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

Ora, ogni volta che vuoi eseguire un comando e stamparlo, puoi fare:

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

Quanto sopra produce questo file:

$ 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

Non intendo spostare qui i pali della porta, ma c'è un modo per far accettare anche il tuo codice alias? Per esempio, se io alias apt-cache dependsa acd, ottengo "No comando 'ACD' trovato, volevi dire: ..." quando corro runcom acd leafpad > out.
DK Bose,

Gli alias @DKBose sono definiti nel file .bashrc, non nella shell, e le funzioni chiamano solo i file binari che si trovano nella variabile $ PATH. Ma puoi fare un semplice trucco. Ad esempio, lsè alias ls --color=auto' nella realtà. Che cosa si potrebbe fare (a patto che non esiste un unico citazioni o doppi apici nel tuo alias), è questa: $ terdonsFunction $(alias ls | awk -F '=' '{$1="";print}'| tr "'" " ") .
Sergiy Kolodyazhnyy,

O trasforma il tuo comando in una variabile. Come ho mostrato nella mia risposta prima. MYCOMMAND="apt-cache depends"; terdonsFunction $MYCOMMAND leafpad > out.txt
Sergiy Kolodyazhnyy,

@Serg, vedi GARCIN Risposta di David: askubuntu.com/a/688936/248158
DK Bose

Questa è la risposta "ovvia" e funziona alla grande a meno che uno qualsiasi degli argomenti riguardi codice che viene eseguito e ha effetti collaterali che potrebbero accumularsi. Questo è un caso limite, quindi non si verificherebbe molto spesso.
Joe,

11

Tu puoi fare:

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

Stessa cosa usando al echoposto di Here stringhe ( <<<):

echo 'apt-cache depends kde-window-manager' | tee file.txt | bash >>file.txt
  • tee scriverà su STDOUT e anche sul file file.txt

  • Lo STDOUT di teeie apt-cache depends kde-window-managerverrà alimentato bashper eseguire il comando e aggiungere lo STDOUT a file.txt.

Esempio:

$ 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
Bella risposta! Semplice e al punto! Ne stavo provando uno teema il mio continuava a fallire. Buon lavoro! +1
Terrance

@Seth Ho anche pensato di giocare con i descrittori di file ma teesembra pulito :)
heemayl

11

Più minimalista - approccio n. 4 e n. 3, entrambi potrebbero essere convertiti in funzione; # 2 il mio preferito - awk. # 1 usa il scriptcomando - strumento molto versatile, utile per registrare la linea di comando in generale; applicabile ovunque, per qualunque cosa tu voglia registrare.

Approccio n. 1: esiste un /usr/bin/scriptcomando (fornito di default con Ubuntu) per la registrazione dell'output della riga di comando, che cattura tutto, insieme al prompt e al comando. Per salvare un solo comando e il suo output in un file specifico, utilizzare -cflag e specificare il file di output. Esempio

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

Approccio n. 2: hacker awk

Awk ha una system()funzione che consente di eseguire comandi shell da awkscript o comando . L'output apparirà sullo schermo, comando prima, output successivo. Per reindirizzare ciò che vedi a un file usa> operatore.

Ciò può essere fatto in due modi: chiedi all'utente di inserire elementi da stdin o come argomento da riga di comando. Il primo è più facile da ottenere, quindi pubblicandolo.

(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) Versione args della riga di comando; non includere l'output per evitare di rispondere troppo a lungo. Ancora una volta, aggiungi >per reindirizzare al file

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

Approccio n. 3: chiedi a bash di fare il lavoro per te

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

Reindirizzare al file con l' >operatore:

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

Approccio n. 4: (il mio secondo preferito)

Ispirato al post di ByteCommander; possiamo usare reade quindi eseguire i comandi necessari in subshell

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

Esecuzione di esempio:

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

Approccio n. 5:

Utilizzare echoo here string(aka <<< "string") per fornire argomenti sh -cattraversoxargs

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 vuoi, puoi usare questo stesso trucco 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 {}; {}"'

Bello, ma non include il comando come fa il codice di Arronical.
DK Bose,

@DKBose Aggiungerò un altro approccio che includerà il comando. Cinque minuti
Sergiy Kolodyazhnyy,

@DKBose come va il mio approccio n. 2?
Sergiy Kolodyazhnyy,

È intelligente, awkè davvero un ragazzo molto configurabile, vero? `lo script sembra utile anche per alcuni altri usi.
Arronical

1
Questa è la risposta migliore perché l'uso dello script evita qualsiasi effetto collaterale derivante da argomenti che potrebbero eseguire il codice quando visualizzato con eco, ecc. - rendendo la seconda esecuzione prevista potrebbe dare risultati diversi rispetto a se il comando fosse eseguito separatamente.
Joe,

6
  1. Inizio script -q outputfile
  2. Esegui il tuo comando
  3. Premi Ctrl-D
  4. Apri il file outputfile

Esempio

Inizio script

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

Inizia il tuo comando

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

Premi Ctrl-D

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

Mostra il tuo comando e output

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

e vedrai qualcosa del genere

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

5

Se vuoi l'espansione dell'alias (solo bash) puoi farlo in questo modo:

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

Ora puoi correre

runcmd acd leafpad > out

4

Potrebbe esserci un modo più semplice, ma puoi farlo con uno script:

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

Crea un file scriptcon questo contenuto nella cartella Home e autorizza l'esecuzione

chmod +x script

Eseguilo in questo modo:

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

Questo approccio ha il vantaggio di semplificare la ripetizione della riga di comando in seguito, se lo si desidera! Puoi anche scrivere il reindirizzamento nello script, in modo da script.shcreare sempre un file chiamato script.logcon il suo output.
Gaurav

4

Soluzione estremamente semplice che utilizza una funzione Bash su una riga

Preparazione:

Questo approccio utilizza una funzione bash personalizzata per fornire la funzionalità desiderata. Lo definisci eseguendo la seguente riga nella sessione del terminale. si noti che è possibile scegliere qualsiasi nome di variabile bash valido anziché runandlog:

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

Ciò tuttavia persiste solo per l'attuale sessione di Bash, il che significa che dopo aver chiuso la finestra del terminale, la funzione sparirà.
Se lo hai provato e ti è piaciuto, puoi renderlo sempre disponibile modificando il tuo ~/.bashrcfile e aggiungendo questa riga alla fine.

Come usare:

Dopo aver definito la funzione, è possibile utilizzarla per eseguire i comandi mentre si registra sia il comando stesso che il suo output in un file. Potresti anche aggiungere ulteriori informazioni come l'utente che l'ha eseguito, che ho già incluso nella funzione, o l'ora esatta in cui è stata eseguita. Le richieste di funzionalità nei commenti sono benvenute! :)

La sintassi è semplice:

runandlog LOGFILENAME YOUR-COMMAND-WITH-ARGUMENTS

Esempio:

Una sessione di esempio come utente bytecommander, che opera dalla home directory potrebbe apparire così:

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

Il che si tradurrà in un nuovo file mylogfile (se esiste già, la funzione aggiungerà l'output ad esso!) Nella directory corrente con il contenuto:

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

3

Un trucco piuttosto non funzionante ma funzionale sarebbe:

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

Brutto, ma funziona!


Accetto questa risposta perché la soluzione è più ampiamente applicabile.
DK Bose,

@DKBose Dovrai digitare il modulo due volte. Ma la soluzione con una sceneggiatura è davvero universale.
Pilota 6

Mi dispiace di dover accettare questa risposta anche se fa quello che ho chiesto. Spero non ti dispiaccia!
DK Bose,

2
Non è un problema @DKBose, sapevo che era una soluzione abbastanza inelegante quando ho inviato la risposta e ho imparato qualcosa di buono dalle risposte alternative pubblicate.
Arronical,

2

Potresti semplicemente passare il comando a una funzione che stamperà prima il comando e successivamente l'output del comando (i reindirizzamenti vengono tenuti intenzionalmente fuori dal comando stampato, puoi facilmente cambiarlo rimuovendo le virgolette dal comando e stampando ed eseguendo $@invece di $1nella funzione):

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

bar

Per aggiungere il comando in seguito, è possibile eseguire questo comando, che inserirà l'ultimo comando eseguito nella parte superiore di un file:

<<<"$(<foo)" cat <(history 2 | sed -n '1s/  [0-9][0-9]*  \(.*\)/\1\n/p') - >foo
  • <<<"[...]": qui stringa; [...]viene reindirizzato a cat's stdin;
  • $(<foo): sostituzione comando; è sostituito dal contenuto di "pippo";
  • cat [...] - >foo: Concatena stdina [...]e uscite a "foo";
  • <([...]): sostituzione del processo: viene sostituito con un descrittore di file contenente l'output di [...];
  • history 2 | sed -n '1s/ [0-9][0-9]* \(.*\)/\1\n/p': genera gli ultimi due comandi, rimuove due spazi seguiti da una o più cifre seguite da due spazi dalla prima riga e lo stampa;
$ 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

Perché stai solo stampando $1? E non ce n'è bisogno eval.
terdon,

@terdon Bene, l'idea era di tenere i reindirizzamenti fuori dal comando stampato, poiché pensavo che questo avrebbe potuto apparire più bello nel caso di OP. Tuttavia, se lo cambio ora sarebbe identico alla tua risposta. Tuttavia sì, evalnon è necessario, non so perché l'ho aggiunto prima. Grazie.
kos,
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.