รวมคำสั่งในไฟล์เอาต์พุตหรือไม่


17

ขออภัยสำหรับชื่อที่สับสน!

สมมติว่าฉันวิ่ง

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

ฉันจะได้รับไฟล์ชื่อ "kwin-dependent" ในโฟลเดอร์ Desktop ของฉัน

มีเคล็ดลับในการรวมคำสั่งที่ฉันใช้เป็นส่วนหนึ่งของไฟล์โดยเฉพาะอย่างยิ่งเมื่อเริ่มต้นไฟล์หรือไม่

อย่างน้อยก็ใน 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ฉันได้รับ "ไม่มีคำสั่ง 'ACD' พบคุณไม่หมายถึง: ..." runcom acd leafpad > outเมื่อผมทำงาน
DK Bose

@DKBose alias ถูกกำหนดในไฟล์. bashrc ไม่ใช่ในเชลล์และฟังก์ชันจะเรียกเฉพาะไฟล์ไบนารีที่อยู่ภายใต้ตัวแปร $ PATH แต่คุณสามารถทำเคล็ดลับง่ายๆ ตัวอย่างเช่นใช้ lsนามแฝงls --color=auto' ในความเป็นจริง สิ่งที่คุณจะทำ (ตราบเท่าที่ไม่มีคำพูดเดียวหรือคำพูดสองในนามแฝงของคุณ) $ terdonsFunction $(alias ls | awk -F '=' '{$1="";print}'| tr "'" " ") คือ:
Sergiy Kolodyazhnyy

หรือเปลี่ยนคำสั่งของคุณเป็นตัวแปร เหมือนที่ฉันแสดงในคำตอบก่อนหน้านี้ MYCOMMAND="apt-cache depends"; terdonsFunction $MYCOMMAND leafpad > out.txt
Sergiy Kolodyazhnyy

@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
Terrance

@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

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) บรรทัดคำสั่ง args เวอร์ชัน; ไม่รวมเอาท์พุทเพื่อหลีกเลี่ยงการตอบนานเกินไป อีกครั้งผนวก>เพื่อเปลี่ยนเส้นทางไปยังไฟล์

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แล้วเรียกใช้คำสั่งที่จำเป็นใน subshell

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(aka <<< "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

@DKBose ฉันจะเพิ่มวิธีการอื่นซึ่งจะรวมคำสั่ง ห้านาที
Sergiy Kolodyazhnyy

@DKB วิธีการของฉันเป็นวิธี # 2?
Sergiy Kolodyazhnyy

นั่นเป็นคนฉลาดawkจริง ๆ เป็นเด็กตัวเล็ก ๆ ที่สามารถกำหนดค่าได้มาก ๆ ไม่ใช่เขา! `สคริปต์ดูมีประโยชน์สำหรับการใช้งานอื่นเช่นกัน
Arronical

1
นี่คือคำตอบที่ดีที่สุดเพราะการใช้สคริปต์หลีกเลี่ยงผลข้างเคียงใด ๆ จากการขัดแย้งซึ่งอาจเรียกใช้รหัสเมื่อแสดงด้วย echo ฯลฯ - การทำครั้งที่สองจุดประสงค์การประมวลผลอาจให้ผลลัพธ์ที่แตกต่างกว่าถ้าคำสั่งถูกเรียกใช้แยกต่างหาก
โจ

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

หากคุณต้องการขยายนามแฝง (ทุบตีเท่านั้น) คุณสามารถทำได้ด้วยวิธีนี้:

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มีเนื้อหานี้ในโฟลเดอร์ Home ของคุณและให้สิทธิ์ดำเนินการ

chmod +x script

ใช้วิธีนี้:

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

วิธีการนี้มีข้อได้เปรียบในการทำให้ง่ายต่อการทำซ้ำบรรทัดคำสั่งนั้นในภายหลังหากคุณต้องการ! นอกจากนี้คุณยังสามารถเขียนการเปลี่ยนเส้นทางไปยังสคริปต์เพื่อscript.shสร้างไฟล์ที่ถูกเรียกscript.logพร้อมกับเอาต์พุต
Gaurav

4

วิธีการแก้ปัญหาที่ง่ายมากโดยใช้ฟังก์ชั่น 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

น่าเกลียด แต่ใช้งานได้!


ฉันยอมรับคำตอบนี้เพราะการแก้ปัญหานั้นมีความครอบคลุมมากกว่า
DK Bose

@DKBose คุณจะต้องพิมพ์โมดูลสองครั้ง แต่ทางออกของสคริปต์นั้นเป็นสากลจริงๆ
Pilot6

ฉันขอโทษที่ฉันต้องยอมรับคำตอบนี้แม้ว่ามันจะเป็นสิ่งที่ฉันขอก็ตาม ฉันหวังว่าคุณจะไม่รังเกียจ!
DK Bose

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's stdin;
  • $(<foo): การทดแทนคำสั่ง; มันถูกแทนที่ด้วยเนื้อหาของ "foo"
  • cat [...] - >foo: เชื่อมstdinต่อ[...]และส่งออกไปยัง "foo";
  • <([...]): การทดแทนกระบวนการ: มันถูกแทนที่ด้วย file descriptor ที่มีเอาต์พุตของ[...];
  • 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
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.