Menjalankan perintah di jendela Terminal Mac OS X baru


92

Saya sudah mencoba mencari cara untuk menjalankan perintah bash di jendela Max OS X Terminal.app yang baru. Sebagai contoh, berikut ini cara saya menjalankan perintah saya dalam proses bash baru:

bash -c "my command here"

Tetapi ini menggunakan kembali jendela terminal yang ada daripada membuat yang baru. Saya ingin sesuatu seperti:

Terminal.app -c "my command here"

Tapi tentu saja ini tidak berhasil. Saya mengetahui perintah "buka -a Terminal.app", tetapi saya tidak melihat cara meneruskan argumen ke terminal, atau bahkan jika saya melakukan argumen apa yang akan digunakan.


Anda selalu dapat membuka preferensi, masuk ke tab "Profil", masuk ke halaman "Shell" dan mengatur perintah startup di sana. Ini hanya berjalan ketika aplikasi dibuka, tetapi berfungsi lebih baik daripada alternatif yang diretas!
Zane Helton

Lihat juga pertanyaan yang sama di superuser superuser.com/q/174576/122841
Beetle

Jawaban:


96

salah satu cara yang bisa saya pikirkan untuk melakukannya di luar kepala saya adalah dengan membuat file .command dan menjalankannya seperti ini:

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

atau gunakan applescript:

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

meskipun Anda harus menghindari banyak tanda kutip ganda atau tidak dapat menggunakan tanda kutip tunggal


Saya telah memutuskan metode pertama. Ini cukup hack-ish, tetapi berhasil dan saya tidak perlu khawatir tentang keluar dari kutipan dalam perintah saya atau apa pun. Terima kasih.
Walt D

3
Jika perintah perlu menjalankan parametrized, mungkin Anda ingin menukar tanda kutip tunggal dan ganda; meskipun Anda perlu memahami perbedaannya agar dapat melakukan ini dengan benar. osascript -e "tell application \"Terminal\" to do script \"echo '$variable'\"'
tripleee

ada yang tahu cara menutup jendela terminal kiri yang bodoh?
Nicholas DiPiazza

Tambahkan ; exitdi akhir perintah skrip shell, seperti do script "echo hello; exit". Anda masih perlu menutup jendela secara terpisah.
tripleee

65

Solusi parsial:

Letakkan hal-hal yang Anda ingin lakukan dalam skrip shell, seperti itu

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

Dan jangan lupa chmod +x fileuntuk membuatnya dapat dieksekusi. Maka kamu bisa

open -a Terminal.app scriptfile

dan itu akan berjalan di jendela baru. Tambahkan ' bash' di akhir skrip agar sesi baru tidak keluar. (Meskipun Anda mungkin harus memikirkan cara memuat rc-files dan sejenisnya kepada pengguna ..)


7
Konteks jendela yang baru dibuka sepertinya adalah folder root pengguna /Users/{username}. Apakah ada cara untuk menjaga folder konteks tetap sama dengan jendela terminal induk yang membukanya?
Johnny Oshika

> Meskipun Anda mungkin harus memikirkan cara memuat rc-files dan sejenisnya kepada pengguna .. gunakan bash -l untuk ini
Aivar

35

Saya sudah mencoba melakukan ini untuk sementara waktu. Berikut ini skrip yang berubah ke direktori kerja yang sama, menjalankan perintah, dan menutup jendela terminal.

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

Tidak suka skrip yang diterima, skrip Anda memecahkan masalah direktori saat ini. Terima kasih!
Marboni

Solusi hebat; itu mengeluarkan sesuatu seperti tab 1 of window id 7433stdout di shell peluncuran . Untuk menekannya, tempatkan >/dev/null sebelumnya <<END .
mklement0

1
Ini tidak secara inheren menutup jendela terminal. Itu hanya keluar dari penerjemah perintah. Terminal.app harus dikonfigurasi untuk menutup jendela secara otomatis, atau saat keluar bersih dari penerjemah perintah.
pengguna66001

8

Jika ada yang peduli, inilah yang setara untuk 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

Berikut ini adalah pandangan lain (juga menggunakan 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' 

lihat: codesnippets.joyent.com/posts/show/1516


3

Saya membuat versi fungsi dari jawaban Oscar, yang ini juga menyalin lingkungan dan perubahan ke direktori yang sesuai

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

Anda bisa menggunakannya seperti ini:

new_window my command here

atau

new_window ssh example.com

1
Saluran ini TMP_FILE="tmp.command"bisa menjadi masalah jika Anda memulai lebih dari satu proses secara bersamaan. Saya akan menyarankan untuk menggantinya denganTMP_FILE=$(mktemp "/tmp/command.XXXXXX")
duthen

2

Ini skrip saya yang luar biasa, ini membuat jendela terminal baru jika diperlukan dan beralih ke direktori Finder jika Finder berada paling depan. Ia memiliki semua mesin yang Anda butuhkan untuk menjalankan perintah.

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

Seorang kolega bertanya kepada saya bagaimana membuka BANYAK sesi ssh sekaligus. Saya menggunakan jawaban cobbal untuk menulis skrip ini:

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

Dengan memperbarui daftar perintah (tidak harus berupa pemanggilan ssh), Anda akan mendapatkan jendela terbuka tambahan untuk setiap perintah yang dijalankan. Pada sleep 60akhirnya ada untuk menyimpan .commandfile di sekitar saat mereka sedang dieksekusi. Jika tidak, shell akan selesai terlalu cepat, menjalankan perangkap untuk menghapus direktori temp (dibuat oleh mktemp) sebelum sesi yang diluncurkan memiliki kesempatan untuk membaca file.


0

Anda juga dapat mengaktifkan fitur perintah baru Terminal dengan menekan Shift + ⌘ + Nkombinasi tombol. Perintah yang Anda masukkan ke dalam kotak akan dijalankan di jendela Terminal baru.


Tentu saja berguna untuk mengetahui, tetapi saya harus melakukannya secara terprogram. Membuat program saya menghasilkan file .command dan kemudian membukanya adalah solusi yang masuk akal (jika agak hack).
Walt D

0

Saya menyebutnya trun skrip. Saya sarankan untuk meletakkannya di direktori di jalur yang dapat dieksekusi. Pastikan itu dapat dieksekusi seperti ini:

chmod +x ~/bin/trun

Kemudian Anda dapat menjalankan perintah di jendela baru hanya dengan menambahkan trun di depannya, seperti ini:

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

Ini skripnya. Itu melakukan beberapa hal mewah seperti meneruskan argumen Anda, mengubah bilah judul, membersihkan layar untuk menghapus kekacauan startup shell, menghapus file ketika selesai. Dengan menggunakan file unik untuk setiap jendela baru, ini dapat digunakan untuk membuat banyak jendela secara bersamaan.

#!/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
Penggunaan yang salah di $*seluruh akan merusak semua kutipan nontrivial dalam masukan. Anda ingin "$@"sebagai gantinya.
tripleee

Saya sedang mencari open -b com.apple.terminal. Terima kasih
Ebru Yener
Dengan menggunakan situs kami, Anda mengakui telah membaca dan memahami Kebijakan Cookie dan Kebijakan Privasi kami.
Licensed under cc by-sa 3.0 with attribution required.