เรียกใช้คำสั่งในหน้าต่างเทอร์มินัล Mac OS X ใหม่


92

ฉันพยายามหาวิธีเรียกใช้คำสั่ง bash ในหน้าต่าง Max OS X Terminal.app ใหม่ ดังตัวอย่างนี่คือวิธีที่ฉันจะเรียกใช้คำสั่งของฉันในกระบวนการทุบตีใหม่:

bash -c "my command here"

แต่จะใช้หน้าต่างเทอร์มินัลที่มีอยู่ซ้ำแทนการสร้างหน้าต่างใหม่ ฉันต้องการสิ่งที่ชอบ:

Terminal.app -c "my command here"

แต่แน่นอนว่าไม่ได้ผล ฉันทราบคำสั่ง "open -a Terminal.app" แต่ฉันไม่เห็นวิธีส่งต่ออาร์กิวเมนต์ไปยังเทอร์มินัลหรือแม้ว่าฉันจะใช้อาร์กิวเมนต์อะไรก็ตาม


คุณสามารถเปิดค่ากำหนดได้ตลอดเวลาไปที่แท็บ "โปรไฟล์" ไปที่หน้า "เชลล์" และตั้งค่าคำสั่งเริ่มต้นที่นั่น จะทำงานเฉพาะเมื่อเปิดแอปพลิเคชัน แต่ทำงานได้ดีกว่าทางเลือกที่แฮ็ก!
Zane Helton

ดูคำถามเดียวกันได้ที่ superuser superuser.com/q/174576/122841
Beetle

คำตอบ:


96

วิธีหนึ่งที่ฉันคิดว่าจะทำออกมาจากด้านบนของหัวคือการสร้างไฟล์. คำสั่งและเรียกใช้ดังนี้:

echo echo hello > sayhi.command; chmod +x sayhi.command; open sayhi.command

หรือใช้ applescript:

osascript -e 'tell application "Terminal" to do script "echo hello"'

แม้ว่าคุณจะต้องหลีกเลี่ยงเครื่องหมายคำพูดคู่จำนวนมากหรือไม่สามารถใช้เครื่องหมายคำพูดเดี่ยวได้


ฉันตัดสินใจเลือกวิธีแรกแล้ว มันค่อนข้างแฮ็ค แต่ใช้งานได้และฉันไม่ต้องกังวลกับการหลบหนีคำพูดในคำสั่งของฉันหรืออะไรเลย ขอบคุณ.
Walt D

3
หากคำสั่งต้องการเรียกใช้พารามีทริกคุณอาจต้องการสลับเครื่องหมายคำพูดเดี่ยวและคู่ แม้ว่าคุณจะต้องเข้าใจความแตกต่างเพื่อให้สามารถทำสิ่งนี้ได้อย่างถูกต้อง osascript -e "tell application \"Terminal\" to do script \"echo '$variable'\"'
tripleee

ใครรู้วิธีปิดหน้าต่างเทอร์มินัลที่เหลือโง่ ๆ
Nicholas DiPiazza

เพิ่ม; exitที่ส่วนท้ายของคำสั่งเชลล์สคริปต์เช่นdo script "echo hello; exit". คุณยังต้องปิดหน้าต่างแยกต่างหาก
tripleee

65

วิธีแก้ปัญหาบางส่วน:

ใส่สิ่งที่คุณต้องการทำในเชลล์สคริปต์เช่นนั้น

#!/bin/bash
ls
echo "yey!"

และอย่าลืม ' chmod +x file' เพื่อให้สามารถใช้งานได้ จากนั้นคุณสามารถ

open -a Terminal.app scriptfile

และจะทำงานในหน้าต่างใหม่ เพิ่ม ' bash' ที่ท้ายสคริปต์เพื่อป้องกันไม่ให้เซสชันใหม่ออก (แม้ว่าคุณอาจต้องหาวิธีโหลดไฟล์ rc และสิ่งต่างๆของผู้ใช้ .. )


7
/Users/{username}บริบทของหน้าต่างที่เพิ่งเปิดใหม่น่าจะเป็นโฟลเดอร์รากของผู้ใช้ มีวิธีใดบ้างที่จะทำให้โฟลเดอร์บริบทเหมือนกับหน้าต่างเทอร์มินัลหลักที่เปิดขึ้นมา
Johnny Oshika

> แม้ว่าคุณอาจต้องหาวิธีโหลดไฟล์ rc และสิ่งต่างๆของผู้ใช้ .. ใช้ bash -l สำหรับสิ่งนี้
Aivar

35

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

#!/bin/sh 
osascript <<END 
tell application "Terminal"
    do script "cd \"`pwd`\";$1;exit"
end tell
END

ไม่ชอบสคริปต์ที่ยอมรับระบบของคุณจะช่วยแก้ปัญหาไดเรกทอรีปัจจุบันได้ ขอบคุณ!
Marboni

ทางออกที่ดี แม้ว่ามันจะส่งผลบางอย่างเช่นtab 1 of window id 7433stdout ในเชลล์เปิดตัว เพื่อให้การปราบปรามที่เกิดขึ้นก่อน>/dev/null <<END
mklement

1
สิ่งนี้ไม่ได้ปิดหน้าต่างเทอร์มินัลโดยเนื้อแท้ เพียงแค่ออกจากตัวแปลคำสั่ง Terminal.app ต้องได้รับการกำหนดค่าให้ปิดหน้าต่างโดยอัตโนมัติหรือเมื่อออกจากตัวแปลคำสั่งทั้งหมด
user66001

8

ในกรณีที่ทุกคนสนใจนี่คือสิ่งที่เทียบเท่ากับ iTerm:

#!/bin/sh
osascript <<END
tell application "iTerm"
 tell the first terminal
  launch session "Default Session"
  tell the last session
   write text "cd \"`pwd`\";$1;exit"
  end tell
 end tell
end tell
END

3

นี่เป็นอีกสิ่งที่ต้องทำ (ใช้ AppleScript ด้วย):

function newincmd() { 
   declare args 
   # escape single & double quotes 
   args="${@//\'/\'}" 
   args="${args//\"/\\\"}" 
   printf "%s" "${args}" | /usr/bin/pbcopy 
   #printf "%q" "${args}" | /usr/bin/pbcopy 
   /usr/bin/open -a Terminal 
   /usr/bin/osascript -e 'tell application "Terminal" to do script with command "/usr/bin/clear; eval \"$(/usr/bin/pbpaste)\""' 
   return 0 
} 

newincmd ls 

newincmd echo "hello \" world" 
newincmd echo $'hello \' world' 

ดู: codenippets.joyent.com/posts/show/1516


3

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

function new_window {
    TMP_FILE=$(mktemp "/tmp/command.XXXXXX")
    echo "#!/usr/bin/env bash" > $TMP_FILE

    # Copy over environment (including functions), but filter out readonly stuff
    set | grep -v "\(BASH_VERSINFO\|EUID\|PPID\|SHELLOPTS\|UID\)" >> $TMP_FILE

    # Copy over exported envrionment
    export -p >> $TMP_FILE

    # Change to directory
    echo "cd $(pwd)" >> $TMP_FILE

    # Copy over target command line
    echo "$@" >> $TMP_FILE

    chmod +x "$TMP_FILE"
    open -b com.apple.terminal "$TMP_FILE"

    sleep .1 # Wait for terminal to start
    rm "$TMP_FILE"
}

คุณสามารถใช้งานได้ดังนี้:

new_window my command here

หรือ

new_window ssh example.com

1
บรรทัดTMP_FILE="tmp.command"อาจเป็นปัญหาได้หากคุณเริ่มมากกว่าหนึ่งกระบวนการพร้อมกัน ฉันขอแนะนำให้เปลี่ยนโดยTMP_FILE=$(mktemp "/tmp/command.XXXXXX")
duthen

2

นี่คือสคริปต์ที่ยอดเยี่ยมของฉันมันจะสร้างหน้าต่างเทอร์มินัลใหม่หากจำเป็นและเปลี่ยนไปใช้ Directory Finder หาก Finder อยู่ด้านหน้าสุด มีเครื่องจักรทั้งหมดที่คุณต้องการเพื่อเรียกใช้คำสั่ง

on run
    -- Figure out if we want to do the cd (doIt)
    -- Figure out what the path is and quote it (myPath)
    try
        tell application "Finder" to set doIt to frontmost
        set myPath to finder_path()
        if myPath is equal to "" then
            set doIt to false
        else
            set myPath to quote_for_bash(myPath)
        end if
    on error
        set doIt to false
    end try

    -- Figure out if we need to open a window
    -- If Terminal was not running, one will be opened automatically
    tell application "System Events" to set isRunning to (exists process "Terminal")

    tell application "Terminal"
        -- Open a new window
        if isRunning then do script ""
        activate
        -- cd to the path
        if doIt then
            -- We need to delay, terminal ignores the second do script otherwise
            delay 0.3
            do script " cd " & myPath in front window
        end if
    end tell
end run

on finder_path()
    try
        tell application "Finder" to set the source_folder to (folder of the front window) as alias
        set thePath to (POSIX path of the source_folder as string)
    on error -- no open folder windows
        set thePath to ""
    end try

    return thePath
end finder_path

-- This simply quotes all occurrences of ' and puts the whole thing between 's
on quote_for_bash(theString)
    set oldDelims to AppleScript's text item delimiters
    set AppleScript's text item delimiters to "'"
    set the parsedList to every text item of theString
    set AppleScript's text item delimiters to "'\\''"
    set theString to the parsedList as string
    set AppleScript's text item delimiters to oldDelims
    return "'" & theString & "'"
end quote_for_bash

1

เพื่อนร่วมงานถามฉันว่าจะเปิดเซสชันจำนวนมากพร้อมกันได้อย่างไร ฉันใช้คำตอบของ Cobbal ในการเขียนสคริปต์นี้:

tmpdir=$( mktemp -d )
trap '$DEBUG rm -rf $tmpdir ' EXIT
index=1

{
cat <<COMMANDS
ssh user1@host1
ssh user2@host2
COMMANDS
} | while read command
do 
  COMMAND_FILE=$tmpdir/$index.command
  index=$(( index + 1 ))
  echo $command > $COMMAND_FILE
  chmod +x  $COMMAND_FILE
  open $COMMAND_FILE
done
sleep 60

ด้วยการอัปเดตรายการคำสั่ง (ไม่จำเป็นต้องเป็นคำสั่ง ssh) คุณจะได้หน้าต่างเปิดเพิ่มเติมสำหรับทุกคำสั่งที่ดำเนินการ sleep 60ในตอนท้ายจะมีการเก็บ.commandไฟล์รอบในขณะที่พวกเขากำลังถูกดำเนินการ มิฉะนั้นเชลล์จะเสร็จสิ้นเร็วเกินไปเรียกใช้กับดักเพื่อลบไดเร็กทอรี temp (สร้างโดย mktemp) ก่อนที่เซสชันที่เรียกใช้จะมีโอกาสอ่านไฟล์


0

คุณยังสามารถเรียกใช้คุณสมบัติคำสั่งใหม่ของ Terminal ได้โดยกดShift + ⌘ + Nคีย์ผสม คำสั่งที่คุณใส่ลงในกล่องจะถูกเรียกใช้ในหน้าต่าง Terminal ใหม่


แน่นอนว่ามีประโยชน์ที่จะรู้ แต่ฉันต้องทำแบบเป็นโปรแกรม การให้โปรแกรมของฉันสร้างไฟล์. คำสั่งจากนั้นเปิดมันเป็นวิธีแก้ปัญหาที่สมเหตุสมผล (หากแฮ็กเล็กน้อย)
Walt D

0

ฉันเรียกสคริปต์นี้ว่า trun ฉันขอแนะนำให้วางไว้ในไดเรกทอรีในเส้นทางปฏิบัติการของคุณ ตรวจสอบให้แน่ใจว่าสามารถใช้งานได้ดังนี้:

chmod +x ~/bin/trun

จากนั้นคุณสามารถเรียกใช้คำสั่งในหน้าต่างใหม่ได้โดยเพิ่ม trun ไว้ข้างหน้าดังนี้:

trun tail -f /var/log/system.log

นี่คือสคริปต์ มันทำสิ่งที่แปลกใหม่เช่นส่งอาร์กิวเมนต์ของคุณเปลี่ยนแถบหัวเรื่องล้างหน้าจอเพื่อลบความยุ่งเหยิงในการเริ่มต้นเชลล์ลบไฟล์เมื่อเสร็จสิ้น ด้วยการใช้ไฟล์ที่ไม่ซ้ำกันสำหรับแต่ละหน้าต่างใหม่จะสามารถใช้เพื่อสร้างหลาย ๆ หน้าต่างในเวลาเดียวกัน

#!/bin/bash
# make this file executable with chmod +x trun
# create a unique file in /tmp
trun_cmd=`mktemp`
# make it cd back to where we are now
echo "cd `pwd`" >$trun_cmd
# make the title bar contain the command being run
echo 'echo -n -e "\033]0;'$*'\007"' >>$trun_cmd
# clear window
echo clear >>$trun_cmd
# the shell command to execute
echo $* >>$trun_cmd
# make the command remove itself
echo rm $trun_cmd >>$trun_cmd
# make the file executable
chmod +x $trun_cmd

# open it in Terminal to run it in a new Terminal window
open -b com.apple.terminal $trun_cmd

1
การใช้งาน$*ตลอดอย่างไม่ถูกต้องจะทำลายการอ้างถึงที่ไม่สำคัญในอินพุต คุณต้องการ"$@"แทน
tripleee

open -b com.apple.terminalผมกำลังมองหา ขอบคุณ
Ebru Yener
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.