Chạy lệnh trong cửa sổ Mac OS X Terminal mới


92

Tôi đang cố gắng tìm ra cách chạy lệnh bash trong cửa sổ Max OS X Terminal.app mới. Ví dụ, đây là cách tôi chạy lệnh của mình trong một quy trình bash mới:

bash -c "my command here"

Nhưng điều này sử dụng lại cửa sổ đầu cuối hiện có thay vì tạo một cửa sổ mới. Tôi muốn một cái gì đó như:

Terminal.app -c "my command here"

Nhưng tất nhiên điều này không hiệu quả. Tôi biết lệnh "open -a Terminal.app", nhưng tôi không biết cách chuyển tiếp các đối số tới thiết bị đầu cuối hoặc ngay cả khi tôi đã sử dụng các đối số nào.


Bạn luôn có thể mở các tùy chọn, truy cập tab "Hồ sơ", chuyển đến trang "Vỏ" và đặt lệnh khởi động ở đó. Nó chỉ chạy khi ứng dụng được mở, nhưng nó hoạt động tốt hơn các lựa chọn thay thế hacky!
Zane Helton

Cũng xem câu hỏi tương tự tại superuser superuser.com/q/174576/122841
Beetle

Câu trả lời:


96

một cách mà tôi có thể nghĩ để thực hiện nó là tạo một tệp .command và chạy nó như sau:

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

hoặc sử dụng applecript:

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

mặc dù bạn sẽ phải thoát nhiều dấu ngoặc kép hoặc không thể sử dụng dấu ngoặc kép


Tôi đã quyết định phương pháp đầu tiên. Nó khá hack-ish, nhưng nó hoạt động và tôi không phải lo lắng về việc thoát dấu ngoặc kép trong lệnh của tôi hoặc bất cứ điều gì. Cảm ơn.
Walt D

3
Nếu lệnh cần chạy được tham số hóa, có lẽ bạn sẽ muốn hoán đổi dấu nháy đơn và dấu nháy kép; mặc dù bạn cần hiểu sự khác biệt để có thể thực hiện điều này một cách chính xác. osascript -e "tell application \"Terminal\" to do script \"echo '$variable'\"'
tripleee

có ai biết cách đóng cửa sổ đầu cuối ngu ngốc còn lại không?
Nicholas DiPiazza

Thêm ; exitvào cuối các lệnh shell script, như do script "echo hello; exit". Bạn vẫn cần đóng cửa sổ riêng biệt.
tripleee

65

Giải pháp một phần:

Đặt những thứ bạn muốn hoàn thành vào một shell-script, như vậy

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

Và đừng quên ' chmod +x file' để làm cho nó có thể thực thi được. Sau đó bạn có thể

open -a Terminal.app scriptfile

và nó sẽ chạy trong một cửa sổ mới. Thêm ' bash' vào cuối tập lệnh để giữ cho phiên mới không bị thoát. (Mặc dù bạn có thể phải tìm ra cách tải tệp rc và nội dung của người dùng ..)


7
Bối cảnh của cửa sổ mới mở dường như là thư mục gốc của người dùng /Users/{username}. Có cách nào để giữ thư mục ngữ cảnh giống như cửa sổ đầu cuối cha đã mở nó không?
Johnny Oshika

> Mặc dù bạn có thể phải tìm ra cách tải tệp rc và nội dung của người dùng .. hãy sử dụng bash -l cho việc này
Aivar

35

Tôi đã cố gắng làm điều này trong một thời gian. Đây là một tập lệnh thay đổi đến cùng một thư mục làm việc, chạy lệnh và đóng cửa sổ đầu cuối.

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

Không thích tập lệnh được chấp nhận, một tập lệnh của bạn giải quyết vấn đề thư mục hiện tại. Cảm ơn!
Marboni

Giải pháp tuyệt vời; Tuy nhiên, nó xuất ra một cái gì đó giống như tab 1 of window id 7433stdout trong trình khởi chạy . Để ngăn chặn điều đó, hãy đặt >/dev/null trước <<END .
mklement0

1
Điều này vốn dĩ không đóng cửa sổ đầu cuối. Nó chỉ thoát khỏi trình thông dịch lệnh. Terminal.app phải được định cấu hình để đóng cửa sổ tự động hoặc khi thoát khỏi trình thông dịch lệnh.
user66001

8

Trong trường hợp bất kỳ ai quan tâm, đây là một tương đương cho 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

Đây là một cách khác về nó (cũng sử dụng 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' 

xem: Codenippets.joyent.com/posts/show/1516


3

Tôi đã tạo một phiên bản chức năng của câu trả lời của Oscar, phiên bản này cũng sao chép môi trường và thay đổi sang thư mục thích hợp

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"
}

Bạn có thể sử dụng nó như thế này:

new_window my command here

hoặc là

new_window ssh example.com

1
Đường dây TMP_FILE="tmp.command"có thể là một vấn đề nếu bạn bắt đầu nhiều quá trình đồng thời. Tôi sẽ đề nghị thay thế nó bằngTMP_FILE=$(mktemp "/tmp/command.XXXXXX")
duthen.

2

Đây là tập lệnh tuyệt vời của tôi, nó tạo một cửa sổ đầu cuối mới nếu cần và chuyển sang thư mục Finder đang ở nếu Finder ở trên cùng. Nó có tất cả các máy móc bạn cần để chạy các lệnh.

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

Một đồng nghiệp đã hỏi tôi làm thế nào để mở RẤT NHIỀU phiên ssh cùng một lúc. Tôi đã sử dụng câu trả lời của cobbal để viết kịch bản này:

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

Bằng cách cập nhật danh sách các lệnh (chúng không phải là lệnh gọi ssh), bạn sẽ nhận được một cửa sổ mở bổ sung cho mọi lệnh được thực thi. Các sleep 60cuối cùng là có để giữ cho các .commandtập tin xung quanh trong khi họ đang được thực thi. Nếu không, trình bao hoàn thành quá nhanh, thực hiện bẫy để xóa thư mục tạm thời (được tạo bởi mktemp) trước khi các phiên khởi chạy có cơ hội đọc tệp.


0

Bạn cũng có thể gọi tính năng lệnh mới của Terminal bằng cách nhấn Shift + ⌘ + Ntổ hợp phím. Lệnh bạn đặt vào hộp sẽ được chạy trong cửa sổ Terminal mới.


Tất nhiên là hữu ích để biết, nhưng tôi cần phải làm điều đó theo chương trình. Để chương trình của tôi tạo một tệp .command và sau đó mở nó là một giải pháp hợp lý (nếu hơi khó hiểu).
Walt D

0

Tôi gọi tập lệnh này là trun. Tôi khuyên bạn nên đặt nó vào một thư mục trong đường dẫn thực thi của bạn. Đảm bảo rằng nó có thể thực thi được như sau:

chmod +x ~/bin/trun

Sau đó, bạn có thể chạy các lệnh trong một cửa sổ mới bằng cách thêm trun trước chúng, như sau:

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

Đây là kịch bản. Nó thực hiện một số việc ưa thích như chuyển các đối số của bạn, thay đổi thanh tiêu đề, xóa màn hình để loại bỏ sự lộn xộn khởi động shell, xóa tệp của nó khi hoàn tất. Bằng cách sử dụng một tệp duy nhất cho mỗi cửa sổ mới, nó có thể được sử dụng để tạo nhiều cửa sổ cùng một lúc.

#!/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
Việc sử dụng sai trong $*suốt sẽ phá hỏng bất kỳ trích dẫn không thường xuyên nào trong đầu vào. Bạn muốn "$@"thay thế.
tripleee

Tôi đã tìm kiếm open -b com.apple.terminal. Cảm ơn
Ebru Yener
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.