Включити команду у вихідний файл?


17

Вибачте за заплутану назву!

Припустимо, я бігаю

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

Я отримаю файл з назвою "kwin-залежно" у своїй папці "Настільний".

Чи є якась хитрість включити команду, яку я видав як частину файлу, бажано на початку файлу?

Так, принаймні в 14.04 LTS, перші кілька рядків виглядатимуть так:

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

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

Замість просто так:

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

3
Оскільки зараз існує багато інших хороших та гнучких рішень, вам, можливо, слід подумати про неприйняття відповіді, яка пропонує вручну написати команду до файлу, ввівши її двічі та замість цього прийняти одне із універсальних рішень.
Байт командир

Відповіді:


18

Я просто використовував би просту функцію. Додайте це до свого ~/.bashrcфайлу:

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

Тепер, коли ви хочете запустити команду та роздрукувати її, ви можете зробити:

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

Наведене вище створює цей файл:

$ 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

Я не маю на увазі переміщати цілі, але чи існує спосіб, щоб ваш код також прийняв псевдоніми? Наприклад, якщо я псевдонім , apt-cache dependsщоб acdя отримую «Ні команди" ДС "знайдено, ви мали в виду: ...» , коли я біг runcom acd leafpad > out.
ДК Бозе

Псевдоніми @DKBose визначаються у файлі .bashrc, а не в оболонці, а функції викликають лише бінарні файли, які знаходяться під змінною $ PATH. Але ви можете зробити просту хитрість. Наприклад, lsвін ls --color=auto' справжній. Що ви могли б зробити ( до тих пір, поки не буде ні одного одинарних або подвійні лапок в псевдонім), полягає в наступному: $ terdonsFunction $(alias ls | awk -F '=' '{$1="";print}'| tr "'" " ") .
Сергій Колодяжний

АБО перетворіть вашу команду в змінну. Як я показав у своїй відповіді раніше. MYCOMMAND="apt-cache depends"; terdonsFunction $MYCOMMAND leafpad > out.txt
Сергій Колодяжний

@Serg, дивіться відповідь GARCIN David: askubuntu.com/a/688936/248158
DK Bose

Це "очевидний" відповідь і чудово працює, якщо жоден з аргументів не включає код, який виконує та має побічні ефекти, які можуть накопичуватися. Це кращий випадок, тому він трапляється не дуже часто.
Джо

11

Ви можете зробити:

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

Те саме, що використовується echoзамість рядків Here ( <<<):

echo 'apt-cache depends kde-window-manager' | tee file.txt | bash >>file.txt
  • tee запише в STDOUT, а також у файл file.txt

  • STDOUT teeie apt-cache depends kde-window-managerбуде поданий bashдля запуску команди та додавання STDOUT до file.txt.

Приклад:

$ 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
Чудова відповідь! Просто і до речі! Я пробував один, teeале мій не вдавався. Хороша робота! +1
Терранс

@Seth Я також думав про те, щоб грати з дескрипторами файлів, але teeздається акуратним :)
heemayl

11

Найбільш мінімалістичний - підхід №4 та №3, обидва можуть бути перетворені на функції; # 2 мій улюблений - awk. №1 використовує scriptкоманду - дуже універсальний інструмент, корисний для запису командного рядка в цілому; застосовується в будь-якому місці для будь-якого, що ви хочете записати.

Підхід №1: Існує /usr/bin/scriptкоманда (яка постачається з ubuntu за замовчуванням) для запису виводу командного рядка, яка фіксує все, разом із запитом та командою. Щоб просто зберегти одну команду та її вихід у певний файл, використовуйте -cпрапор та вкажіть вихідний файл. Приклад

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

Підхід №2: аварійний хакерство

Awk має system()функцію, яка дозволяє запускати команди оболонки зі awkсценарію або команди . Вихід з’явиться на екрані, команда спочатку, виведення далі. Щоб перенаправити побачене >оператору використання файлів .

Це можна зробити двома способами - попросіть користувача ввести матеріали з stdin або як аргумент командного рядка. По-перше, це легше досягти, а значить, розмістити це.

(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) версія аргументів командного рядка; не включаючи вихід, щоб уникнути занадто довгого відповіді Знову додайте >до переадресації до файлу

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

Підхід №3: попросіть Баша виконати роботу за вас

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

Перенаправлення на файл > оператором:

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

Підхід №4: (мій другий улюблений)

Натхненний публікацією ByteCommander; ми можемо використовуватиread а потім запускати необхідні команди в підпакеті

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

Проба зразка:

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

Підхід №5:

Використовуйте echoабо here string(ака <<< "string"), щоб надати аргументи sh -cнаскрізь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

І якщо ви хочете, ви можете використовувати цей самий трюк з псевдонімом:

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 {}; {}"'

Приємно, але вона не включає команду так, як робить код Arronical.
ДК Бозе

@DKBose Я додам ще один підхід, який буде включати команду. П'ять хвилин
Сергій Колодяжний

@DKBose Як мій підхід №2?
Сергій Колодяжний

Це розумно, awkнасправді це дуже налаштований маленький хлопчик, чи не він! `Сценарій виглядає зручним і для деяких інших застосувань.
Арронічний

1
Це найкраща відповідь, оскільки використання скрипту дозволяє уникнути будь-яких побічних ефектів від аргументів, які можуть виконувати код, коли відображається із відлунням, і т.д.
Джо

6
  1. Старт script -q outputfile
  2. Виконай команду
  3. Натисніть Ctrl-D
  4. Відкрийте файл outputfile

Приклад

Старт script

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

Почніть свою команду

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

Натисніть Ctrl-D

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

Покажіть свою команду та виведіть

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

і ви побачите щось подібне

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

5

Якщо ви хочете розширити псевдонім (лише bash), ви можете зробити це так:

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

Тепер ви можете бігти

runcmd acd leafpad > out

4

Можливо, є простіший спосіб, але ви можете це зробити за сценарієм:

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

Створіть файл scriptіз цим вмістом у своїй домашній папці та дайте дозвіл на виконання

chmod +x script

Виконайте це так:

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

Цей підхід має перевагу в тому, що це легко повторити цей командний рядок пізніше, якщо ви хочете! Ви також можете записати перенаправлення в сценарій, щоб script.shзавжди створювався файл, який викликається script.logз його висновком.
Гаурав

4

Надзвичайно просте рішення з використанням однолінійної функції Bash

Підготовка:

Цей підхід використовує власну функцію bash, щоб забезпечити бажану функціональність. Ви визначаєте його, виконавши наступний рядок у своєму сеансі терміналу. зауважте, що ви можете обрати будь-яке дійсне ім'я змінної bash замість runandlog:

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

Це, однак, зберігається лише для поточного сеансу Bash, тобто означає, що після закриття вікна термінала функція буде відсутня.
Якщо ви спробували і сподобалось вам, ви можете зробити це завжди доступним, редагуючи свій~/.bashrc файл і додавши цей рядок до кінця.

Як користуватись:

Визначивши функцію, ви можете використовувати її для запуску команд під час реєстрації як самої команди, так і її виводу у файл. Ви можете навіть додати більше інформації, як користувач, який її виконав, якого я вже включив у функцію, або точний час її запуску. Особливості запитів у коментарях вітаються! :)

Синтаксис простий:

runandlog LOGFILENAME YOUR-COMMAND-WITH-ARGUMENTS

Приклад:

Приклад сеансу роботи користувача bytecommander, що працює з домашнього каталогу, може виглядати так:

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

У результаті чого новий файл mylogfile (якщо він вже існує, функція додасть до нього вихід!) У поточному каталозі зі вмістом:

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

3

Досить нечистим, але функціональним фокусом було б:

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

Некрасиво, але це працює!


Я приймаю цю відповідь, тому що рішення є більш загальним.
ДК Бозе

@DKBose Можливо, вам доведеться вводити модуль двічі. Але рішення зі сценарієм справді універсальне.
Пілот6

Мені шкода, що я маю не прийняти цю відповідь, навіть якщо вона робить те, про що я просив. Сподіваюся, ви не заперечуєте!
ДК Босе

2
Не проблема @DKBose, я знав, що це досить неелегантне рішення, коли я подав відповідь, і дізнався кілька хороших речей з розміщених альтернативних відповідей.
Арронічний

2

Ви можете просто передати команду функції, яка спочатку буде надрукувати команду, а потім вивести команду (перенаправлення навмисно не виводяться з друкованої команди. Ви можете легко змінити це, видаливши лапки з команди та друкуючи та виконуючи $@замість цього з $1в функції):

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

bar

Щоб потім додати команду, ви можете запустити цю команду, яка вставить останню команду, виконану у верхній частині файлу:

<<<"$(<foo)" cat <(history 2 | sed -n '1s/  [0-9][0-9]*  \(.*\)/\1\n/p') - >foo
  • <<<"[...]": тут рядок; [...]перенаправляється на cat'sstdin ;
  • $(<foo): підміна команд; його замінено на вміст "foo";
  • cat [...] - >foo: з'єднує stdinв [...]та виводить на "foo";
  • <([...]): заміна процесу: замінюється дескриптором файлів, що містить вихід [...];
  • history 2 | sed -n '1s/ [0-9][0-9]* \(.*\)/\1\n/p': виводить дві останні команди, видаляє два пробіли, за якими слідує одна чи більше цифр, а потім два пробіли з першого рядка та друкує його;
$ 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

Чому ти тільки друкуєш $1? І в цьому немає потреби eval.
тердон

@terdon Ну, ідея полягала в тому, щоб не перенаправляти друковану команду, оскільки я вважав, що це може виглядати приємніше у випадку ОП. Тим не менш, якщо я зараз його зміню, це було б ідентично вашій відповіді. Однак так, evalне потрібно, не впевнений, чому я додав його раніше. Спасибі.
kos
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.