Sertakan perintah dalam file output?

17

Maaf untuk judul yang membingungkan!

Misalkan saya lari

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

Saya akan mendapatkan file bernama "kwin-depend" di folder Desktop saya.

Apakah ada beberapa trik untuk memasukkan perintah yang saya keluarkan sebagai bagian dari file, terutama pada awal file?

Jadi, setidaknya dalam 14,04 LTS, beberapa baris pertama akan terlihat seperti ini:

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

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

Alih-alih hanya seperti ini:

kde-window-manager
  Depends: kde-runtime
  Depends: libc6
 |Depends: libegl1-mesa
  Depends: <libegl1-x11>
DK Bose
sumber
3
Karena sekarang ada banyak solusi bagus dan fleksibel lainnya, Anda mungkin harus mempertimbangkan untuk tidak menerima jawaban yang menyarankan untuk menulis perintah secara manual ke file dengan mengetiknya dua kali dan menerima salah satu solusi serbaguna sebagai gantinya.
Byte Commander

Jawaban:

18

Saya hanya akan menggunakan fungsi sederhana. Tambahkan ini ke ~/.bashrcfile Anda :

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

Sekarang, kapan pun Anda ingin menjalankan perintah dan mencetaknya, Anda dapat melakukan:

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

Di atas menghasilkan file ini:

$ 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
sumber
Saya tidak bermaksud untuk memindahkan tiang gawang di sini, tetapi apakah ada cara untuk mendapatkan kode Anda untuk menerima alias juga? Misalnya, jika saya alias apt-cache dependsuntuk acd, saya mendapatkan "Tidak ada perintah 'acd' ditemukan, maksud Anda: ..." ketika saya menjalankan runcom acd leafpad > out.
DK Bose
Alias ​​@DKBose didefinisikan dalam file .bashrc, bukan di shell, dan fungsinya hanya memanggil file biner yang terletak di bawah variabel $ PATH. Tetapi Anda bisa melakukan trik sederhana. Misalnya, lsalias ls --color=auto' dalam kenyataan. Apa yang Anda bisa lakukan (selama tidak ada tanda kutip tunggal atau tanda kutip ganda alias Anda), adalah ini: $ terdonsFunction $(alias ls | awk -F '=' '{$1="";print}'| tr "'" " ") .
Sergiy Kolodyazhnyy
ATAU ubah perintah Anda menjadi variabel. Seperti yang saya tunjukkan dalam jawaban saya sebelumnya. MYCOMMAND="apt-cache depends"; terdonsFunction $MYCOMMAND leafpad > out.txt
Sergiy Kolodyazhnyy
@Serg, silakan lihat jawaban GARCIN David: askubuntu.com/a/688936/248158
DK Bose
Ini adalah jawaban "jelas" dan berfungsi dengan baik kecuali jika ada argumen yang melibatkan kode yang mengeksekusi dan memiliki efek samping yang mungkin menumpuk. Ini adalah kasus tepi, jadi itu tidak akan sering terjadi.
Joe
11

Anda dapat melakukan:

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

Hal yang sama menggunakan echoalih-alih string Here ( <<<):

echo 'apt-cache depends kde-window-manager' | tee file.txt | bash >>file.txt
  • tee akan menulis ke STDOUT dan juga ke file file.txt

  • STDOUT teeyaitu apt-cache depends kde-window-managerakan diumpankan bashuntuk menjalankan perintah dan menambahkan STDOUT ke file.txt.

Contoh:

$ 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
sumber
1
Jawaban bagus! Sederhana dan to the point! Saya mencoba satu dengan teetetapi saya terus gagal. Kerja bagus! +1
Terrance
@Seth Saya juga berpikir tentang bermain dengan deskriptor file tetapi teetampaknya rapi :)
heemayl
11

Paling minimalis - pendekatan # 4 dan # 3, keduanya dapat dikonversi menjadi fungsi; # 2 favorit saya - awk. # 1 menggunakan scriptperintah - alat yang sangat serbaguna, berguna untuk merekam baris perintah secara umum; berlaku di mana saja, untuk apa pun yang ingin Anda rekam.

Pendekatan # 1: Ada /usr/bin/scriptperintah (yang datang dengan ubuntu secara default) untuk merekam output baris perintah, yang menangkap semuanya, bersama dengan prompt dan perintah. Untuk hanya menyimpan satu perintah dan outputnya ke file tertentu, gunakan -cflag dan tentukan file output. Contoh

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

Pendekatan # 2: awk hackery

Awk memiliki system()fungsi yang memungkinkan Anda menjalankan perintah shell dari awkskrip atau perintah . Output akan muncul di layar, perintah pertama, output selanjutnya. Untuk mengarahkan ulang apa yang Anda lihat ke penggunaan file> operator .

Itu dapat dilakukan dengan dua cara - meminta pengguna untuk memasukkan barang dari stdin atau sebagai argumen baris perintah. Yang pertama lebih mudah untuk dicapai, maka mempostingnya.

(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 baris perintah args; tidak termasuk output untuk menghindari membuat jawaban terlalu lama. Sekali lagi, tambahkan >untuk mengarahkan ulang ke file

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

Pendekatan # 3: minta bash untuk melakukan pekerjaan untuk Anda

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

Redirect ke file dengan >operator:

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

Pendekatan # 4: (favorit kedua saya)

Terinspirasi oleh pos ByteCommander; kita bisa menggunakan readdan menjalankan perintah yang diperlukan dalam subkulit

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

Contoh dijalankan:

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

Pendekatan # 5:

Gunakan echoatau here string(alias <<< "string") untuk memberikan argumen sh -cmelaluixargs

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

Dan jika Anda mau, Anda bisa menggunakan trik yang sama ini dengan 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
sumber
Bagus, tetapi tidak termasuk perintah seperti yang dilakukan kode Arronical.
DK Bose
@DKenutup Saya akan menambahkan pendekatan lain yang akan menyertakan perintah. Lima menit
Sergiy Kolodyazhnyy
@DKingkar, bagaimana pendekatan saya # 2?
Sergiy Kolodyazhnyy
Itu pintar, awkbenar-benar teman kecil yang sangat bisa diatur, bukan? Skrip `terlihat berguna untuk beberapa kegunaan lain juga.
Arronical
1
Ini adalah jawaban terbaik karena menggunakan skrip menghindari efek samping dari argumen yang dapat mengeksekusi kode ketika ditampilkan dengan gema, dll. - membuat eksekusi kedua, yang dimaksudkan, mungkin memberikan hasil yang berbeda daripada jika perintah dijalankan secara terpisah.
Joe
6
  1. Mulailah script -q outputfile
  2. Jalankan perintah Anda
  3. Tekan Ctrl-D
  4. Buka file outputfile

Contoh

Mulailah script

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

Mulai perintahmu

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

Tekan Ctrl-D

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

Tampilkan perintah dan output Anda

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

dan Anda akan melihat sesuatu seperti ini

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

Jika Anda ingin ekspansi alias (khusus bash) Anda dapat melakukannya dengan cara ini:

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

Anda sekarang dapat berlari

runcmd acd leafpad > out
GARCIN David
sumber
4

Mungkin ada cara yang lebih mudah, tetapi Anda bisa melakukannya dengan skrip:

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

Buat file scriptdengan konten ini di folder Beranda dan berikan izin eksekusi

chmod +x script

Jalankan dengan cara ini:

./script kde-window-manager > ~/Desktop/kwin-depends
Pilot6
sumber
Pendekatan ini memiliki keuntungan membuatnya mudah untuk mengulangi baris perintah itu nanti jika Anda mau! Anda juga dapat menulis pengalihan ke skrip, sehingga script.shselalu membuat file yang disebut script.logdengan hasilnya.
Gaurav
4

Solusi yang sangat sederhana menggunakan fungsi Bash satu baris

Persiapan:

Pendekatan ini menggunakan fungsi bash khusus untuk menyediakan fungsionalitas yang diinginkan. Anda mendefinisikannya dengan mengeksekusi baris berikut dalam sesi terminal Anda. perhatikan bahwa Anda dapat memilih nama variabel bash yang valid alih-alih runandlog:

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

Namun ini hanya berlanjut untuk sesi Bash saat ini, itu berarti setelah menutup jendela terminal, fungsi akan hilang.
Jika Anda mencoba dan menyukainya, Anda dapat membuatnya selalu tersedia dengan mengedit ~/.bashrcfile Anda dan menambahkan baris ini sampai akhir.

Cara Penggunaan:

Setelah mendefinisikan fungsi, Anda dapat menggunakannya untuk menjalankan perintah sambil mencatat perintah itu sendiri dan hasilnya ke file. Anda bahkan dapat menambahkan lebih banyak informasi seperti pengguna yang mengeksekusinya, yang sudah saya sertakan ke dalam fungsi, atau waktu yang tepat untuk menjalankannya. Permintaan fitur dalam komentar dipersilahkan! :)

Sintaksnya sederhana:

runandlog LOGFILENAME YOUR-COMMAND-WITH-ARGUMENTS

Contoh:

Sesi contoh sebagai pengguna bytecommander, yang beroperasi dari direktori home dapat terlihat seperti ini:

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

Yang akan menghasilkan file baru mylogfile (jika sudah ada, fungsi akan menambahkan output ke sana!) Di direktori saat ini dengan konten:

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

Trik yang cukup tidak jelas tetapi fungsional adalah:

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

Jelek, tapi berhasil!

Arronikal
sumber
Saya menerima jawaban ini karena solusinya lebih luas berlaku.
DK Bose
@ DKBose Anda harus mengetik modul dua kali. Tetapi solusi dengan skrip benar-benar universal.
Pilot6
Saya minta maaf saya harus menerima jawaban ini meskipun itu melakukan apa yang saya minta. Saya harap kamu tidak keberatan!
DK Bose
2
Bukan masalah @DKBose, saya tahu itu adalah solusi yang cukup tidak tepat ketika saya mengirimkan jawabannya, dan telah mempelajari beberapa hal bagus dari jawaban alternatif yang diposting.
Arronikal
2

Anda bisa meneruskan perintah ke fungsi yang akan mencetak perintah terlebih dahulu dan output perintah setelah itu (pengalihan disimpan dari perintah yang dicetak dengan sengaja, Anda dapat dengan mudah mengubah ini dengan menghapus tanda kutip dari perintah dan dengan mencetak dan menjalankan $@sebagai gantinya dari $1dalam fungsi):

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

bar

Untuk menambahkan perintah setelahnya, Anda dapat menjalankan perintah ini, yang akan menyisipkan perintah terakhir yang dijalankan di bagian atas file:

<<<"$(<foo)" cat <(history 2 | sed -n '1s/  [0-9][0-9]*  \(.*\)/\1\n/p') - >foo
  • <<<"[...]": di sini string; [...]diarahkan ke cat's stdin;
  • $(<foo): substitusi perintah; diganti dengan konten "foo";
  • cat [...] - >foo: digabungkan stdinke [...]dan output ke "foo";
  • <([...]): subtitusi proses: diganti dengan deskriptor file yang berisi output [...];
  • history 2 | sed -n '1s/ [0-9][0-9]* \(.*\)/\1\n/p': menampilkan dua perintah terakhir, menghilangkan dua spasi diikuti oleh satu atau lebih digit diikuti oleh dua spasi dari baris pertama dan mencetaknya;
$ 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
sumber
Mengapa Anda hanya mencetak $1? Dan tidak perlu eval.
terdon
@terdon Yah, idenya adalah untuk menjaga pengalihan dari perintah yang dicetak, karena saya pikir ini mungkin terlihat lebih bagus dalam kasus OP. Nontheless jika saya mengubahnya sekarang akan identik dengan jawaban Anda. Namun ya, evaltidak diperlukan, tidak yakin mengapa saya menambahkannya sebelumnya. Terima kasih.
kos