Inclure la commande dans le fichier de sortie?

17

Désolé pour le titre déroutant!

Supposons que je cours

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

J'obtiendrai un fichier nommé "kwin-depend" dans mon dossier Desktop.

Existe-t-il une astuce pour inclure la commande que j'ai émise dans le fichier, de préférence au début du fichier?

Donc, au moins en 14.04 LTS, les premières lignes ressembleraient à ceci:

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

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

Au lieu de juste comme ça:

kde-window-manager
  Depends: kde-runtime
  Depends: libc6
 |Depends: libegl1-mesa
  Depends: <libegl1-x11>
DK Bose
la source
3
Comme il existe maintenant de nombreuses autres solutions bonnes et flexibles, vous devriez peut-être envisager d'accepter la réponse qui suggère d'écrire manuellement la commande dans le fichier en la tapant deux fois et d'accepter l'une des solutions polyvalentes à la place.
Byte Commander

Réponses:

18

J'utiliserais simplement une fonction simple. Ajoutez ceci à votre ~/.bashrcfichier:

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

Maintenant, chaque fois que vous souhaitez exécuter une commande et l'imprimer, vous pouvez faire:

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

Ce qui précède produit ce fichier:

$ 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
terdon
la source
Je ne veux pas déplacer les poteaux ici, mais existe-t-il un moyen pour que votre code accepte également les alias? Par exemple, si je alias apt-cache dependspour acd, je reçois « Aucune commande « DAA » trouvé, avez - vous dire: ... » quand je lance runcom acd leafpad > out.
DK Bose
Les alias @DKBose sont définis dans le fichier .bashrc, pas dans le shell, et les fonctions appellent uniquement les fichiers binaires situés sous la variable $ PATH. Mais vous pouvez faire un truc simple. Par exemple, lsest aliasé ls --color=auto' dans la réalité. Qu'est - ce que vous pourriez faire (tant qu'il n'y a pas de guillemets simples ou doubles guillemets dans votre pseudonyme), est la suivante: $ terdonsFunction $(alias ls | awk -F '=' '{$1="";print}'| tr "'" " ") .
Sergiy Kolodyazhnyy
OU transformez votre commande en variable. Comme je l'ai montré dans ma réponse auparavant. MYCOMMAND="apt-cache depends"; terdonsFunction $MYCOMMAND leafpad > out.txt
Sergiy Kolodyazhnyy
@Serg, veuillez voir la réponse de GARCIN David: askubuntu.com/a/688936/248158
DK Bose
C'est la réponse "évidente" et fonctionne très bien à moins qu'aucun des arguments n'implique un code qui s'exécute et a des effets secondaires qui pourraient s'accumuler. Ceci est un cas de bord, donc il ne se produirait pas très souvent.
Joe
11

Tu peux faire:

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

Même chose en utilisant echoau lieu de Here strings ( <<<):

echo 'apt-cache depends kde-window-manager' | tee file.txt | bash >>file.txt
  • tee écrira dans STDOUT et aussi dans le fichier file.txt

  • Le STDOUT de teeie apt-cache depends kde-window-managersera alimenté bashpour exécuter la commande et ajouter le STDOUT à file.txt.

Exemple:

$ 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>
heemayl
la source
1
Très bonne réponse! Simple et au point! J'en essayais un avec teemais le mien continuait à échouer. Bon travail! +1
Terrance
@Seth, j'ai aussi pensé à jouer avec les descripteurs de fichiers, mais ça me teesemble bien :)
heemayl
11

Le plus minimaliste - approche # 4 et # 3, les deux pourraient être convertis en fonction; # 2 mon préféré - awk. # 1 utilise la scriptcommande - outil très polyvalent, utile pour enregistrer la ligne de commande en général; applicable partout, pour tout ce que vous voulez enregistrer.

Approche n ° 1: il existe une /usr/bin/scriptcommande (fournie avec ubuntu par défaut) pour enregistrer la sortie de ligne de commande, qui capture tout, ainsi que l'invite et la commande. Pour simplement enregistrer une commande et sa sortie dans un fichier spécifique, utilisez l' -cindicateur et spécifiez le fichier de sortie. Exemple

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

Approche n ° 2: piratage awk

Awk a une system()fonction qui vous permet d'exécuter des commandes shell à partir d'un awkscript ou d'une commande . La sortie apparaîtra sur l'écran, la commande d'abord, la sortie ensuite. Pour rediriger ce que vous voyez vers un >opérateur d' utilisation de fichier .

Cela peut être fait de deux manières - demandez à l'utilisateur de saisir des éléments depuis stdin ou comme argument de ligne de commande. Le premier est plus facile à réaliser, d'où son affichage.

(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) Version args de la ligne de commande; n'inclut pas la sortie pour éviter de répondre trop longtemps. Encore une fois, ajoutez >pour rediriger vers le fichier

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

Approche n ° 3: demandez à bash de faire le travail pour vous

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

Rediriger vers un fichier avec l' >opérateur:

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

Approche n ° 4: (mon deuxième favori)

Inspiré par le post de ByteCommander; nous pouvons utiliser readpuis exécuter les commandes nécessaires en sous-shell

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

Exemple d'exécution:

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

Approche n ° 5:

Utilisez echoou here string(aka <<< "string") pour fournir des arguments à sh -ctraversxargs

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

Et si vous le souhaitez, vous pouvez utiliser cette même astuce avec 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 {}; {}"'
Sergiy Kolodyazhnyy
la source
Bien, mais il n'inclut pas la commande comme le fait le code d'Arronical.
DK Bose du
@DKBose J'ajouterai une autre approche qui inclura la commande. Cinq minutes
Sergiy Kolodyazhnyy
@DKBose comment est mon approche # 2?
Sergiy Kolodyazhnyy
C'est intelligent, c'est awkvraiment un petit gars très configurable n'est-ce pas! `Le script semble également utile pour quelques autres utilisations.
Arronical
1
C'est la meilleure réponse, car l'utilisation du script évite tout effet secondaire des arguments qui pourraient exécuter du code lorsqu'il est affiché avec echo, etc.
Joe
6
  1. Début script -q outputfile
  2. Exécutez votre commande
  3. Presse Ctrl-D
  4. Ouvrez le dossier outputfile

Exemple

Début script

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

Lancez votre commande

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

Presse Ctrl-D

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

Montrez votre commande et sortie

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

et vous verrez quelque chose comme ça

[aboettger:~/tmp] % apt-cache depends kde-window-manager
<kde-window-manager>
UN B
la source
5

Si vous souhaitez une extension d'alias (bash uniquement), vous pouvez le faire de cette façon:

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

Vous pouvez maintenant exécuter

runcmd acd leafpad > out
GARCIN David
la source
4

Il peut y avoir un moyen plus simple, mais vous pouvez le faire par un script:

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

Créez un fichier scriptavec ce contenu dans votre dossier d'accueil et donnez la permission d'exécution

chmod +x script

Exécutez-le de cette façon:

./script kde-window-manager > ~/Desktop/kwin-depends
Pilot6
la source
Cette approche a l'avantage de faciliter la répétition de cette ligne de commande plus tard si vous le souhaitez! Vous pouvez également écrire la redirection dans le script, ce qui script.shcrée toujours un fichier appelé script.logavec sa sortie.
Gaurav
4

Solution extrêmement simple utilisant une fonction Bash d'une ligne

Préparation:

Cette approche utilise une fonction bash personnalisée pour fournir la fonctionnalité souhaitée. Vous le définissez en exécutant la ligne suivante dans votre session de terminal. notez que vous pouvez choisir n'importe quel nom de variable bash valide au lieu de runandlog:

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

Cependant, cela ne persiste que pour la session Bash en cours, ce qui signifie qu'après la fermeture de la fenêtre du terminal, la fonction aura disparu.
Si vous l'avez essayé et aimé, vous pouvez le rendre toujours disponible en modifiant votre ~/.bashrcfichier et en ajoutant cette ligne à la fin de celui-ci.

Comment utiliser:

Après avoir défini la fonction, vous pouvez l'utiliser pour exécuter des commandes tout en enregistrant la commande elle-même et sa sortie dans un fichier. Vous pouvez même ajouter plus d'informations comme l'utilisateur qui l'a exécutée, que j'ai déjà inclus dans la fonction, ou l'heure exacte à laquelle elle a été exécutée. Les demandes de fonctionnalités dans les commentaires sont les bienvenues! :)

La syntaxe est simple:

runandlog LOGFILENAME YOUR-COMMAND-WITH-ARGUMENTS

Exemple:

Un exemple de session en tant qu'utilisateur bytecommander, fonctionnant à partir du répertoire personnel pourrait ressembler à ceci:

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

Ce qui entraînera un nouveau fichier mylogfile (s'il existe déjà, la fonction y ajoutera la sortie!) Dans le répertoire courant avec le contenu:

[bytecommander] $ fortune 
A mathematician is a device for turning coffee into theorems.
        -- P. Erdos
Byte Commander
la source
3

Une astuce assez onclever mais fonctionnelle serait:

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

Laid, mais ça marche!

Arronical
la source
J'accepte cette réponse car la solution est plus largement applicable.
DK Bose du
@DKBose Vous devrez taper le module deux fois. Mais la solution avec un script est vraiment universelle.
Pilot6
Je suis désolé de devoir refuser cette réponse même si elle fait ce que j'ai demandé. J'espère que ça ne vous dérange pas!
DK Bose
2
Pas de problème @DKBose, je savais que c'était une solution assez inélégante lorsque j'ai soumis la réponse, et j'ai appris de bonnes choses à partir des réponses alternatives publiées.
Arronical
2

Vous pouvez simplement passer la commande à une fonction qui imprimera la commande en premier et la sortie de la commande ensuite (les redirections sont conservées intentionnellement hors de la commande imprimée, vous pouvez facilement changer cela en supprimant les guillemets de la commande et en imprimant et en exécutant à la $@place de $1dans la fonction):

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

bar

Pour ajouter la commande par la suite, vous pouvez exécuter cette commande, qui insérera la dernière commande exécutée en haut d'un fichier:

<<<"$(<foo)" cat <(history 2 | sed -n '1s/  [0-9][0-9]*  \(.*\)/\1\n/p') - >foo
  • <<<"[...]": ici chaîne; [...]est redirigé vers catl » stdin;
  • $(<foo): substitution de commande; il est remplacé par le contenu de "foo";
  • cat [...] - >foo: Concatène stdinà [...]et sorties « foo »;
  • <([...]): substitution de processus: il est remplacé par un descripteur de fichier contenant la sortie de [...];
  • history 2 | sed -n '1s/ [0-9][0-9]* \(.*\)/\1\n/p': affiche les deux dernières commandes, supprime deux espaces suivis d'un ou plusieurs chiffres suivis de deux espaces de la première ligne et l'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
kos
la source
Pourquoi n'imprimez-vous que $1? Et ce n'est pas nécessaire eval.
terdon
@terdon Eh bien, l'idée était de garder les redirections hors de la commande imprimée, car je pensais que cela aurait pu être plus joli dans le cas d'OP. Néanmoins, si je le change maintenant, ce serait identique à votre réponse. Cependant oui, ce evaln'est pas nécessaire, je ne sais pas pourquoi je l'ai ajouté avant. Merci.
kos