Bao gồm lệnh trong tập tin đầu ra?


17

Xin lỗi vì tiêu đề khó hiểu!

Giả sử tôi chạy

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

Tôi sẽ nhận được một tệp có tên "kwin-phụ thuộc" trong thư mục Máy tính để bàn của tôi.

Có một số mẹo để bao gồm lệnh tôi đã ban hành như một phần của tệp, tốt nhất là khi bắt đầu tệp?

Vì vậy, ít nhất là trong 14.04 LTS, một vài dòng đầu tiên sẽ trông như thế này:

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

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

Thay vì chỉ như thế này:

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

3
Vì hiện nay có nhiều giải pháp tốt và linh hoạt khác, bạn có thể nên xem xét để không chấp nhận câu trả lời gợi ý viết thủ công lệnh vào tệp bằng cách nhập hai lần và chấp nhận một trong các giải pháp đa năng thay thế.
Chỉ huy Byte

Câu trả lời:


18

Tôi sẽ chỉ sử dụng một chức năng đơn giản. Thêm phần này vào ~/.bashrctập tin của bạn :

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

Bây giờ, bất cứ khi nào bạn muốn chạy một lệnh và in nó, bạn có thể làm:

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

Ở trên tạo ra tệp này:

$ 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

Tôi không có ý di chuyển các cột mục tiêu ở đây, nhưng có cách nào để mã của bạn chấp nhận bí danh không? Ví dụ, nếu tôi bí danh apt-cache dependsđể acd, tôi nhận được "Không có lệnh 'ACD' tìm thấy, bạn đã có nghĩa là: ..." khi tôi chạy runcom acd leafpad > out.
Công lý cho Monica

Các bí danh @DKBose được định nghĩa trong tệp .bashrc, không phải trong shell và các hàm chỉ gọi các tệp nhị phân nằm dưới biến $ PATH. Nhưng bạn có thể làm một thủ thuật đơn giản. Ví dụ, lsđược đặt bí danh ls --color=auto' trong thực tế. Những gì bạn có thể làm (miễn là không có dấu ngoặc đơn hoặc dấu ngoặc kép trong bí danh của bạn), là đây : $ terdonsFunction $(alias ls | awk -F '=' '{$1="";print}'| tr "'" " ") .
Sergiy Kolodyazhnyy

HOẶC biến lệnh của bạn thành một biến. Giống như tôi đã thể hiện trong câu trả lời của mình trước đây. MYCOMMAND="apt-cache depends"; terdonsFunction $MYCOMMAND leafpad > out.txt
Sergiy Kolodyazhnyy

@Serg, vui lòng xem câu trả lời của GARCIN David: Askubfox.com/a/688936/248158
Công lý cho Monica

Đây là câu trả lời "rõ ràng" và hoạt động tuyệt vời trừ khi bất kỳ đối số nào liên quan đến mã thực thi và có tác dụng phụ có thể tích lũy. Đây là một trường hợp cạnh, vì vậy nó sẽ không xảy ra rất thường xuyên.
Joe

11

Bạn có thể làm:

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

Điều tương tự bằng cách sử dụng echothay vì chuỗi ở đây ( <<<):

echo 'apt-cache depends kde-window-manager' | tee file.txt | bash >>file.txt
  • tee sẽ ghi vào STDOUT và cả vào tập tin file.txt

  • STDOUT của teetức là apt-cache depends kde-window-managersẽ được cung cấp bashđể chạy lệnh và nối STDOUT vào file.txt.

Thí dụ:

$ 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
Câu trả lời chính xác! Ngắn gọn và đúng trọng tâm! Tôi đã thử một lần teenhưng tôi vẫn thất bại. Làm tốt lắm! +1
Terrance

@ Tôi cũng đã nghĩ về việc chơi với các mô tả tập tin nhưng teecó vẻ gọn gàng :)
heemayl

11

Tối giản nhất - cách tiếp cận # 4 và # 3, cả hai đều có thể được chuyển đổi thành chức năng; # 2 yêu thích của tôi - awk. # 1 sử dụng scriptlệnh - công cụ rất linh hoạt, hữu ích để ghi dòng lệnh nói chung; áp dụng bất cứ nơi nào, cho bất cứ điều gì bạn muốn ghi lại.

Cách tiếp cận # 1: Có một /usr/bin/scriptlệnh (đi kèm với ubfox theo mặc định) để ghi đầu ra dòng lệnh, ghi lại mọi thứ, cùng với dấu nhắc và lệnh. Để chỉ lưu một lệnh và đầu ra của nó vào tệp cụ thể, hãy sử dụng -ccờ và chỉ định tệp đầu ra. Thí dụ

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

Cách tiếp cận # 2: hackk awk

Awk có system()chức năng cho phép bạn chạy các lệnh shell từ awkscript hoặc lệnh . Đầu ra sẽ hiển thị trên màn hình, lệnh đầu tiên, đầu ra tiếp theo. Để chuyển hướng những gì bạn thấy đến một >toán tử sử dụng tập tin .

Điều đó có thể được thực hiện theo hai cách - yêu cầu người dùng nhập nội dung từ stdin hoặc làm đối số dòng lệnh. Đầu tiên là dễ dàng để đạt được, do đó gửi bài đó.

(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) Phiên bản dòng lệnh args; không bao gồm đầu ra để tránh trả lời quá lâu. Một lần nữa, nối >để chuyển hướng đến tập tin

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

Cách tiếp cận số 3: yêu cầu bash thực hiện công việc cho bạn

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

Chuyển hướng đến tập tin với >toán tử:

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

Cách tiếp cận số 4: (yêu thích thứ hai của tôi)

Lấy cảm hứng từ bài viết của ByteCommander; chúng ta có thể sử dụng readvà sau đó chạy các lệnh cần thiết trong subshell

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

Chạy mẫu:

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

Cách tiếp cận số 5:

Sử dụng echohoặc here string(aka <<< "string") để cung cấp các đối số sh -cthông quaxargs

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

Và nếu bạn muốn, bạn có thể sử dụng thủ thuật tương tự với bí danh:

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

Đẹp, nhưng nó không bao gồm lệnh theo cách mã của Arronical.
Công lý cho Monica

@DKBose Tôi sẽ thêm một cách tiếp cận khác sẽ bao gồm lệnh. Năm phút
Sergiy Kolodyazhnyy

@DKBose cách tiếp cận số 2 của tôi như thế nào?
Sergiy Kolodyazhnyy

Thật thông minh, awkthực sự là một cậu bé rất dễ cấu hình phải không anh! `script trông cũng tiện cho một vài mục đích sử dụng khác.
Arronical

1
Đây là câu trả lời tốt nhất vì sử dụng tập lệnh sẽ tránh mọi tác dụng phụ từ các đối số có thể thực thi mã khi được hiển thị bằng tiếng vang, v.v. - thực hiện lần thứ hai, dự định, thực thi có thể cho kết quả khác so với khi lệnh được chạy riêng.
Joe

6
  1. Khởi đầu script -q outputfile
  2. Thực hiện lệnh của bạn
  3. Nhấn Ctrl-D
  4. Mở tập tin outputfile

Thí dụ

Khởi đầu script

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

Bắt đầu lệnh của bạn

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

Nhấn Ctrl-D

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

Hiển thị lệnh và đầu ra của bạn

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

và bạn sẽ thấy một cái gì đó như thế này

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

5

Nếu bạn muốn mở rộng bí danh (chỉ bash), bạn có thể làm theo cách này:

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

Bây giờ bạn có thể chạy

runcmd acd leafpad > out

4

Có thể có một cách dễ dàng hơn, nhưng bạn có thể thực hiện nó bằng một tập lệnh:

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

Tạo một tệp scriptcó nội dung này trong thư mục Nhà của bạn và cho phép thực thi

chmod +x script

Chạy theo cách này:

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

Cách tiếp cận này có ưu điểm là làm cho nó dễ dàng lặp lại dòng lệnh đó sau nếu bạn muốn! Bạn cũng có thể viết chuyển hướng vào tập lệnh, để script.shluôn tạo một tệp được gọi script.logvới đầu ra của nó.
Gaurav

4

Giải pháp cực kỳ đơn giản sử dụng hàm Bash một dòng

Sự chuẩn bị:

Cách tiếp cận này sử dụng chức năng bash tùy chỉnh để cung cấp chức năng mong muốn. Bạn xác định nó bằng cách thực hiện dòng sau trong phiên cuối của bạn. lưu ý rằng bạn có thể chọn bất kỳ tên biến bash hợp lệ nào thay vì runandlog:

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

Tuy nhiên, điều này chỉ tồn tại cho phiên Bash hiện tại, có nghĩa là sau khi đóng cửa sổ terminal, chức năng sẽ biến mất.
Nếu bạn đã thử và thích nó, bạn có thể làm cho nó luôn có sẵn bằng cách chỉnh sửa ~/.bashrctệp của bạn và nối dòng này vào cuối của nó.

Cách sử dụng:

Sau khi đã xác định hàm, bạn có thể sử dụng nó để chạy các lệnh trong khi ghi nhật ký cả lệnh và đầu ra của nó vào một tệp. Bạn thậm chí có thể thêm nhiều thông tin như người dùng đã thực thi nó, mà tôi đã đưa vào chức năng, hoặc thời gian chính xác nó đã được chạy. Yêu cầu tính năng trong ý kiến ​​được chào đón! :)

Cú pháp rất đơn giản:

runandlog LOGFILENAME YOUR-COMMAND-WITH-ARGUMENTS

Thí dụ:

Một phiên ví dụ là người dùng bytecommander, hoạt động từ thư mục chính có thể trông như thế này:

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

Điều này sẽ dẫn đến một tệp mới mylogfile (nếu nó đã tồn tại, hàm sẽ nối đầu ra cho nó!) Trong thư mục hiện tại với nội dung:

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

3

Một mẹo khá khó hiểu nhưng chức năng sẽ là:

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

Xấu xí, nhưng nó hoạt động!


Tôi chấp nhận câu trả lời này vì giải pháp được áp dụng rộng rãi hơn.
Công lý cho Monica

@DKBose Bạn sẽ phải gõ mô-đun hai lần. Nhưng giải pháp với một kịch bản là thực sự phổ quát.
Pilot6

Tôi xin lỗi vì tôi phải không chấp nhận câu trả lời này mặc dù nó làm những gì tôi yêu cầu. Tôi hy vọng bạn không phiền!
Công lý cho Monica

2
Không phải là vấn đề @DKBose, tôi biết đó là một giải pháp khá không phù hợp khi tôi gửi câu trả lời và đã học được một số nội dung hay từ các câu trả lời thay thế được đăng.
Arronical

2

Bạn có thể chỉ cần chuyển lệnh đến một chức năng sẽ in lệnh trước và đầu ra của lệnh sau đó (các chuyển hướng được giữ ngoài lệnh in có chủ ý, bạn có thể dễ dàng thay đổi điều này bằng cách xóa dấu ngoặc kép khỏi lệnh và bằng cách in và chạy $@thay thế của $1trong hàm):

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

bar

Để thêm lệnh sau đó, bạn có thể chạy lệnh này, lệnh này sẽ chèn lệnh cuối cùng chạy ở đầu tệp:

<<<"$(<foo)" cat <(history 2 | sed -n '1s/  [0-9][0-9]*  \(.*\)/\1\n/p') - >foo
  • <<<"[...]": đây chuỗi; [...]được chuyển hướng đến cat'sstdin ;
  • $(<foo): thay thế lệnh; nó được thay thế bằng nội dung của "foo";
  • cat [...] - >foo: Concatenates stdinđến [...]và đầu ra để "foo";
  • <([...]): thay thế quá trình: nó được thay thế bằng một bộ mô tả tệp có chứa đầu ra của [...];
  • history 2 | sed -n '1s/ [0-9][0-9]* \(.*\)/\1\n/p': xuất ra hai lệnh cuối cùng, loại bỏ hai khoảng trắng theo sau bởi một hoặc nhiều chữ số theo sau là hai khoảng trắng từ dòng đầu tiên và in ra nó;
$ 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

Tại sao bạn chỉ in $1? Và không cần eval.
terdon

@terdon Chà, ý tưởng là để tránh các chuyển hướng ra khỏi lệnh được in, vì tôi nghĩ rằng nó có thể trông đẹp hơn trong trường hợp của OP. Không cần thiết nếu tôi thay đổi nó bây giờ nó sẽ giống hệt với câu trả lời của bạn. Tuy nhiên, có, evalkhông cần thiết, không chắc tại sao tôi lại thêm nó trước đây. Cảm ơn.
kos
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.