Yeni bir Mac OS X Terminal penceresinde bir komut çalıştırma


92

Yeni bir Max OS X Terminal.app penceresinde bir bash komutunun nasıl çalıştırılacağını anlamaya çalışıyorum. Örnek olarak, yeni bir bash işleminde komutumu nasıl çalıştıracağım:

bash -c "my command here"

Ancak bu, yeni bir tane oluşturmak yerine mevcut terminal penceresini yeniden kullanır. Ben şöyle bir şey istiyorum:

Terminal.app -c "my command here"

Ama elbette bu işe yaramıyor. "Open -a Terminal.app" komutunun farkındayım, ancak argümanları terminale nasıl ileteceğimi ya da hangi argümanları kullanacağımı yapsam bile bilmiyorum.


Her zaman tercihleri ​​açabilir, "Profiller" sekmesine gidebilir, "Kabuk" sayfasına gidebilir ve orada başlatma komutunu ayarlayabilirsiniz. Yalnızca uygulama açıldığında çalışır, ancak hacky alternatiflerinden daha iyi çalışır!
Zane Helton

Aynı soruyu superuser superuser.com/q/174576/122841
Beetle

Yanıtlar:


96

aklımın ucunda yapmayı düşünmemin bir yolu, bir .command dosyası oluşturmak ve bu şekilde çalıştırmaktır:

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

veya el yazısı kullanın:

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

Ya çok sayıda çift tırnak işaretinden kaçmanız gerekecek ya da tek tırnak kullanamayacaksınız


İlk yönteme karar verdim. Oldukça hack-ish, ama işe yarıyor ve komutumdaki alıntılardan kaçmak konusunda endişelenmeme gerek yok. Teşekkürler.
Walt D

3
Komutun parametreleştirilmiş çalışması gerekiyorsa, belki de tek ve çift tırnakları değiştirmek isteyeceksiniz; Ancak bunu doğru bir şekilde yapabilmek için farkı anlamanız gerekir. osascript -e "tell application \"Terminal\" to do script \"echo '$variable'\"'
2016

aptal sol terminal penceresini nasıl kapatacağını bilen var mı?
Nicholas DiPiazza

; exitGibi, kabuk betiği komutlarının sonuna ekleyin do script "echo hello; exit". Yine de pencereyi ayrı ayrı kapatmanız gerekiyor.
üçlü

65

Kısmi çözüm:

Yapılmasını istediğiniz şeyleri bir kabuk komut dosyasına koyun.

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

Ve chmod +x fileçalıştırılabilir hale getirmeyi ' ' unutmayın . O zaman yapabilirsin

open -a Terminal.app scriptfile

ve yeni bir pencerede çalışacaktır. bashYeni oturumun çıkmaması için komut dosyasının sonuna ' ' ekleyin . (Kullanıcıların rc dosyalarını ve eşyalarını nasıl yükleyeceğinizi bulmanız gerekse de ..)


7
Yeni açılan pencerenin bağlamı, kullanıcının kök klasörü gibi görünüyor /Users/{username}. Bağlam klasörünü, onu açan ana terminal penceresi ile aynı tutmanın bir yolu var mı?
Johnny Oshika

> Kullanıcıların rc dosyalarını ve malzemelerini nasıl yükleyeceğinizi
bulmanız gerekse de

35

Bunu bir süredir yapmaya çalışıyorum. İşte aynı çalışma dizinine değişen, komutu çalıştıran ve terminal penceresini kapatan bir komut dosyası.

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

Kabul edilen komut dizisinden hoşlanmayın, sizin mevcut dizin sorununu çözersiniz. Teşekkürler!
Marboni

Harika çözüm; yine tab 1 of window id 7433de başlatma kabuğunda stdout gibi bir şey çıktılar . , Yeri o bastırmak için >/dev/null önce <<END .
mklement0

1
Bu, doğal olarak terminal penceresini kapatmaz. Sadece komut yorumlayıcısından çıkar. Terminal.app, pencereyi otomatik olarak kapatacak şekilde veya komut yorumlayıcının temiz çıkışında yapılandırılmalıdır.
user66001

8

Birinin umursaması durumunda, işte iTerm için bir eşdeğer:

#!/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

İşte yine başka bir yaklaşım (ayrıca AppleScript kullanarak):

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' 

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


3

Oscar'ın cevabının bir işlev versiyonunu yaptım, bu da ortamı kopyalar ve uygun dizine değişir

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

Bunu şu şekilde kullanabilirsiniz:

new_window my command here

veya

new_window ssh example.com

1
Aynı TMP_FILE="tmp.command"anda birden fazla işlemi başlatırsanız, hat sorun olabilir. Bunu şu şekilde değiştirmenizi öneririmTMP_FILE=$(mktemp "/tmp/command.XXXXXX")
duthen

2

İşte benim harika betiğim, gerekirse yeni bir terminal penceresi oluşturur ve Finder en öndeyse Finder'ın bulunduğu dizine geçer. Komutları çalıştırmak için ihtiyacınız olan tüm makinelere sahiptir.

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

Bir meslektaşım bana aynı anda BİRÇOK ssh oturumunu nasıl açacağımı sordu. Bu senaryoyu yazmak için kobbalın cevabını kullandım:

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

Komutların listesini güncelleyerek (ssh çağrıları olmaları gerekmez), çalıştırılan her komut için ek bir açık pencere elde edersiniz. sleep 60Sonunda tutmak için vardır .commandidam edilirken etrafında dosyaları. Aksi takdirde, başlatılan oturumlar dosyaları okuma fırsatına sahip olmadan önce kabuk (mktemp tarafından oluşturulan) geçici dizini silmek için tuzağı çalıştırarak çok hızlı tamamlanır.


0

Tuş kombinasyonuna basarak Terminal'in yeni komut özelliğini de çağırabilirsiniz Shift + ⌘ + N. Kutuya koyduğunuz komut yeni bir Terminal penceresinde çalıştırılacaktır.


Elbette bilmekte fayda var, ancak bunu programlı olarak yapmam gerekiyor. Programımın bir .command dosyası oluşturması ve ardından onu açması makul bir çözümdür (biraz hack olsa da).
Walt D

0

Ben bu senaryoya trun diyorum. Çalıştırılabilir yolunuzdaki bir dizine koymanızı öneririm. Şu şekilde çalıştırılabilir olduğundan emin olun:

chmod +x ~/bin/trun

Ardından komutları yeni bir pencerede, önlerine trun ekleyerek çalıştırabilirsiniz, örneğin:

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

İşte senaryo. Argümanlarınızı geçmek, başlık çubuğunu değiştirmek, kabuk başlangıç ​​karmaşasını gidermek için ekranı temizlemek, bittiğinde dosyasını kaldırmak gibi bazı süslü şeyler yapar. Her yeni pencere için benzersiz bir dosya kullanarak, aynı anda birçok pencere oluşturmak için kullanılabilir.

#!/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
$*Boy boyunca yanlış kullanım , girdideki önemsiz alıntıları mahveder. Onun "$@"yerine istiyorsun .
üçlü

Arıyordum open -b com.apple.terminal. Teşekkürler
Ebru Yener
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.