在新的Mac OS X终端窗口中运行命令


89

我一直在尝试找出如何在新的Max OS X Terminal.app窗口中运行bash命令。作为示例,这是在新的bash进程中运行命令的方式:

bash -c "my command here"

但这将重用现有的终端窗口,而不是创建一个新的窗口。我想要类似的东西:

Terminal.app -c "my command here"

但是,当然这是行不通的。我知道“ open -a Terminal.app”命令,但是我看不到如何将参数转发到终端,甚至我没有使用什么参数。


您始终可以打开首选项,转到“配置文件”选项卡,进入“外壳”页面并在此处设置启动命令。它仅在打开应用程序时运行,但比其他选择更有效!
Zane Helton,2015年

Answers:


95

我可以想到的一种方法是创建一个.command文件并按如下方式运行它:

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

或使用applescript:

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

尽管您要么必须转义很多双引号,要么就不能使用单引号


我已经决定了第一种方法。这确实有点hacking,但是它可以工作,我不必担心命令或其他内容中的引号会被转义。谢谢。
Walt D

3
如果该命令需要参数化运行,则可能需要交换单引号和双引号。尽管您需要了解差异才能正确执行此操作。osascript -e "tell application \"Terminal\" to do script \"echo '$variable'\"'
Tripleee 2013年

有谁知道如何关闭终端窗口上剩下的笨蛋?
尼古拉斯·迪广场

; exit在shell脚本命令的末尾添加,例如do script "echo hello; exit"。您仍然需要单独关闭窗口。
Tripleee

65

部分解决方案:

将您想要完成的事情放在shell脚本中,如下所示

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

并且不要忘记chmod +x file使其成为可执行文件。那么你就可以

open -a Terminal.app scriptfile

它将在新窗口中运行。bash在脚本末尾添加“ ”,以防止新会话退出。(尽管您可能必须弄清楚如何加载用户的rc文件和内容。)


7
新打开的窗口的上下文似乎是用户的根文件夹/Users/{username}。有什么方法可以使上下文文件夹与打开它的父终端窗口相同?
约翰尼·奥什卡

>尽管您可能必须弄清楚如何加载用户rc文件和内容。.为此使用bash -l
Aivar

35

我已经尝试了一段时间。这是一个脚本,该脚本将更改为相同的工作目录,运行命令,然后关闭终端窗口。

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

不喜欢接受的脚本,您可以解决当前目录问题。谢谢!
马波尼2012年

很好的解决方案;但是,它tab 1 of window id 7433启动外壳中输出类似于stdout的内容。要抑制这种情况,请放在>/dev/null 之前 <<END
mklement0

1
这并不是从本质上关闭终端窗口。它只是退出命令解释器。必须将Terminal.app配置为自动关闭窗口,或在命令解释器的干净退出时关闭窗口。
user66001 2013年

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' 

请参阅:codesnippets.joyent.com/posts/show/1516


3

我制作了Oscar答案的功能版本,该版本还复制了环境并将其更改到适当的目录

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

这是我很棒的脚本,如果需要,它会创建一个新的终端窗口,如果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

一位同事问我如何一次打开很多ssh会话。我用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正在执行,而他们周围的文件。否则,shell将完成得太快,在启动的会话有机会读取文件之前执行陷阱以删除temp目录(由mktemp创建)。


0

您也可以通过按组合键来调用Terminal 的新命令功能Shift + ⌘ + N。放入框中的命令将在新的“终端”窗口中运行。


知道当然有用,但是我需要以编程方式进行。让我的程序生成一个.command文件,然后将其打开是一个合理的(如果有点黑)的解决方案。
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 18/09/25

我一直在寻找open -b com.apple.terminal。谢谢
Ebru Yener
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.