在输出文件中包含命令?


17

抱歉,标题令人迷惑!

假设我跑步

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

我将在“桌面”文件夹中得到一个名为“ kwin-depends”的文件。

是否有一些技巧可以将我发出的命令作为文件的一部分包括在内,最好在文件的开头?

因此,至少在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
由于现在还有许多其他好的且灵活的解决方案,您可能应该考虑拒绝接受以下答案:通过两次键入命令将命令手动写入文件,然后接受一种通用解决方案。
字节指挥官

Answers:


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 dependsacd,我得到“无命令‘ACD’发现,你的意思是:” ......当我运行runcom acd leafpad > out
DK Bose 2015年

@DKBose别名是在.bashrc文件中定义的,而不是在Shell中定义的,并且函数仅调用$ PATH变量下的二进制文件。但是您可以做一个简单的技巧。例如, 实际上ls是别名ls --color=auto'。你可以做的(只要是在你的别名没有单引号或双引号),这就是: $ terdonsFunction $(alias ls | awk -F '=' '{$1="";print}'| tr "'" " ")
Sergiy Kolodyazhnyy 2015年

或者将您的命令转换为变量。就像我之前在答案中显示的那样。MYCOMMAND="apt-cache depends"; terdonsFunction $MYCOMMAND leafpad > out.txt
Sergiy Kolodyazhnyy 2015年

@Serg,请参阅GARCIN David的回答:askubuntu.com/a/688936/248158
DK Bose

这是“显而易见”的答案,并且效果很好,除非任何参数都涉及执行的代码并具有可能累积的副作用。这是一个极端的情况,因此不会经常发生。

11

你可以做:

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

使用相同的东西echo代替这里的字符串(<<<):

echo 'apt-cache depends kde-window-manager' | tee file.txt | bash >>file.txt
  • tee 将写入STDOUT以及文件 file.txt

  • teeie 的STDOUT 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
Terrance

@Seth我也考虑过使用文件描述符,但tee看起来很整洁:)
heemayl 2015年

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骇客

Awk具有system()允许您awk脚本或命令运行shell命令的功能。输出将显示在屏幕上,首先显示命令,然后显示输出。要将看到的内容重定向到文件,请使用>运算符。

这可以通过两种方式完成-要求用户从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:要求Bash为您完成工作

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:

使用echohere 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的代码那样包含命令。
DK Bose 2015年

@DKBose我将添加另一种方法,该方法将包括命令。五分钟
Sergiy Kolodyazhnyy 2015年

@DKBose我的方法#2如何?
2015年

那很聪明,awk真的是一个可配置的小家伙,不是吗!脚本看起来也很方便用于其他用途。
Arronical

1
这是最佳答案,因为使用脚本避免了参数的任何副作用,这些参数在与回声等一起显示时可能会执行代码。-与单独运行命令相比,有计划地进行第二次执行可能会得出不同的结果。
2015年

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带有其输出的文件。
加拉夫2015年

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在主目录中以user身份运行的示例会话如下所示:

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

丑陋,但是行得通!


我接受此答案,因为该解决方案适用范围更广。
DK Bose 2015年

@DKBose您将不得不两次键入模块。但是使用脚本的解决方案确实是通用的。
试点

很抱歉,即使它满足了我的要求,我也不得不接受这个答案。希望您不要介意!
DK Bose 2015年

2
@DKBose没问题,我知道这是一个相当微不足道的解决方案,因为我提交了答案,并且从发布的替代答案中学到了一些好东西。
Arronical

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
  • <<<"[...]":这里的字符串; [...]重定向到catstdin
  • $(<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

@terdon好吧,我的想法是将重定向保留在打印命令之外,因为我认为在OP的情况下看起来可能更好。但是,如果我现在更改它,它将与您的答案相同。但是,是的,eval不需要,不确定我为什么要添加它。谢谢。
kos 2015年
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.