【问题标题】:Programmatically launch Terminal.app with a specified command (and custom colors)使用指定的命令(和自定义颜色)以编程方式启动 Terminal.app
【发布时间】:2011-05-23 04:47:22
【问题描述】:

我可以像这样从命令行(或程序,通过系统调用)启动 xterm:

/usr/X11/bin/xterm -fg SkyBlue -bg black -e myscript

这将启动一个带有蓝色文本和黑色背景的 xterm,并在其中运行任意脚本。

我的问题:如何使用 Terminal.app 进行等效操作?

【问题讨论】:

  • 我想一种方法是创建多个版本的 ~/Library/Preferences/com.apple.Terminal.plist,然后使用适当的版本启动终端。 plist文件可以在命令行指定吗?

标签: macos command-line terminal applescript


【解决方案1】:

你也可以通过bundle id打开一个应用,并提供其他参数。

如果当前目录下有可执行脚本test.sh,会在Terminal.app中打开并运行以下命令

 open -b com.apple.terminal test.sh 

我能找到的唯一缺点是终端似乎没有继承您当前的环境,因此您必须安排另一种方式将参数传递给您要运行的脚本。我猜想动态构建脚本以嵌入参数是一种方法(当然要考虑到安全隐患......)

【讨论】:

  • 这并不能直接解决颜色问题,但它是在终端窗口中启动现有 shell 脚本的更好方法。
【解决方案2】:

假设您的一个终端配置文件中已经有了您想要的颜色,这就是我想出的(在Juha's answerthis Serverfault answer 的帮助下)。


更新:

回想起来,我觉得这个echo 的业务太复杂了。事实证明,您可以使用 osascript 制作带有 shebang 行的可执行 AppleScript 文件:

#!/usr/bin/osascript                                                                            

on run argv                                                                                     
  if length of argv is equal to 0                                                               
    set command to ""                                                                           
  else                                                                                          
    set command to item 1 of argv                                                               
  end if                                                                                        

  if length of argv is greater than 1                                                           
    set profile to item 2 of argv                                                               
    runWithProfile(command, profile)                                                            
  else                                                                                          
    runSimple(command)                                                                          
  end if                                                                                        
end run                                                                                         

on runSimple(command)                                                                           
  tell application "Terminal"                                                                   
    activate                                                                                    
    set newTab to do script(command)                                                            
  end tell                                                                                      
  return newTab                                                                                 
end runSimple                                                                                   

on runWithProfile(command, profile)                                                             
  set newTab to runSimple(command)                                                              
  tell application "Terminal" to set current settings of newTab to (first settings set whose name is profile)                                                                                      
end runWithProfile

将其保存为term.scpt,使用chmod +x 使其可执行,并以与以下相同的方式使用它,例如term.scpt "emacs -nw" "Red Sands".


原答案:

假设我们将下面的脚本保存为term.sh...

#!/bin/sh

echo '
on run argv
  if length of argv is equal to 0
    set command to ""
  else
    set command to item 1 of argv
  end if

  if length of argv is greater than 1
    set profile to item 2 of argv
    runWithProfile(command, profile)
  else
    runSimple(command)
  end if
end run

on runSimple(command)
  tell application "Terminal"
    activate
    set newTab to do script(command)
  end tell
  return newTab
end runSimple

on runWithProfile(command, profile)
  set newTab to runSimple(command)
  tell application "Terminal" to set current settings of newTab to (first settings set whose name is profile)
end runWithProfile
' | osascript - "$@" > /dev/null

...可以如下调用:

  • term.sh
    • 打开一个新的终端窗口,没什么特别的
  • term.sh COMMAND
    • 打开一个新的终端窗口,执行指定的命令。带参数的命令可以用引号引起来,例如term.sh "emacs -nw" 打开一个新终端并运行(非窗口)emacs
  • term.sh COMMAND PROFILE
    • 打开一个新的终端窗口,执行指定的命令,并将其设置为指定的配置文件。名称中带有空格的配置文件可以用引号引起来,例如term.sh "emacs -nw" "Red Sands" 打开一个新终端并使用 Red Sands 配置文件运行(非窗口)emacs。

如果您使用错误的命令名调用它,它仍会打开窗口并设置配置文件,但您会在新窗口中收到 bash 的错误消息。

如果您使用错误的配置文件名称调用它,窗口仍会打开,命令仍将执行,但窗口将坚持使用默认配置文件,并且您将收到一条错误消息(无论您启动它到 stderr 的位置)的线条

525:601:执行错误:终端出错:无法获取名称 =“elvis”的设置集 1。无效索引。 (-1719)

调用有点hacky,如果我花时间学习getopt,可能会得到改进(例如,term.sh -p profile -e command 之类的东西会更好,例如,可以让您轻松打开一个新终端指定的配置文件而不调用命令)。如果有办法用复杂的引用搞砸它,我也不会感到惊讶。但它适用于大多数用途。

【讨论】:

  • 有效!我已经等了4年了。 :) 谢谢。
  • 感谢脚本!不幸的是,在我的电脑中,如果终端尚未激活,它总是会打开 2 个终端窗口。任何想法如何避免这种情况?
  • @Aivar 嗯,我不确定。我的猜测是它与activatedo script() 有关,但我不是终端/Applescript 专家。
  • 这不会在终端中启动 term.scpt 的当前工作目录中的进程。使用第一种形式(使用 bash)并将 `set 命令添加到 "cd '$PWD' ;" & command` 所以 sh 可以插入 $PWD。如果 PWD 包含空格,这将不起作用,但解决方法是重新调整 sh 的引用。我将发布另一个答案。
  • 我每天都需要打开许多终端以通过 SSH 连接到不同的机器上进行 wrk,而且我的配置文件很挑剔......谢谢你;节省了我各种时间!
【解决方案3】:

几乎所有(每个?)osx 程序都可以使用以下命令从命令行启动:

appName.app/Contents/MacOS/command

对于终端,命令是:

/Applications/Utilities/Terminal.app/Contents/MacOS/Terminal

您可以使用自动完成(制表符)或 ls 来查找正确的文件名。 “.app”基本上是一个文件夹。

要更改颜色并运行脚本...我认为您不能使用 shell 脚本来执行此操作,因为终端不接受参数(“终端 myScript.sh”不启动 myScript)。使用 iTerm 即可。

解决方法是使用 applescript(包装在 shell 脚本中):

   #!/bin/sh
   osascript -e '
     tell application "Terminal"
       activate
       tell window 1
          do script "sleep 5; exit"
          set background color to {0, 11111, 11111}
          set win_id to id
       end tell

       set w_ids to (id of every window)

       repeat while w_ids contains win_id
         delay 1
         set w_ids to (id of every window)
       end repeat
    end tell'

好的,现在它的行为应该与 xterm 示例完全相同。缺点是不断轮询窗口 id(这是不好的编程)。

编辑: 更优雅的applescript 将使用终端的'busy' 属性。我将保留原始代码原样用于一般程序(不仅仅是终端)。

tell application "Terminal"
    tell window 1
        do script "sleep 2"
        set background color to {0, 11111, 11111}
        repeat while busy
            delay 1
        end repeat
        close
    end tell
end tell

同样对于完全正确的程序,应该检查终端是否正在运行。它会影响打开的窗口数量。所以,这应该首先运行(又是一个看起来很讨厌的 hack,我稍后会在找到工作解决方案时对其进行编辑)。

tell application "System Events"
    if (count (processes whose name is "Terminal")) is 0 then
        tell application "Terminal"
            tell window 1
                close
            end tell
        end tell
    end if
end tell

br,
朱哈

【讨论】:

  • 我刚刚发现这与 xterm 等效项之间的一个区别:调用此 shell 脚本会立即返回,而不是等待命令(在您的示例中为“echo boo”)完成。你知道如何让它等待吗?再次感谢!
  • @dreeves:啊,您可以将“脚本”更改为“shell 脚本”并删除“with command”。我稍微修改一下答案...
  • @Juha:感谢您的修复!我现在在 epsilon 内,可能可以自己解决这个问题,但你知道如何防止脚本输出窗口 id 列表吗? (我也认为这可能有点太丑陋了,我应该接受它并制作一个合适的 Cocoa 应用程序,而不是在终端中启动脚本的所有这些骇客!)
  • 我添加了一个更优雅的替代脚本(不使用 id)。
  • 非常感谢您提供的所有帮助!新版本实际上根本不适合我。窗口立即打开和关闭。我在你有“sleep 2”的地方使用的脚本等待用户在标准输入上输入。也许这不会像预期的那样响应“忙时延迟”检查?
【解决方案4】:

您还可以进入终端 GUI,根据您的需要完全配置选项,然后将它们导出到“.terminal”文件,和/或将配置分组到窗口组中并将其导出到终端文件“myGroup” 。终端”。那么

打开 myGroup.terminal

将立即打开终端,并配置所有设置和启动命令。

【讨论】:

  • 在 Sierra 上,Shell -> Export Settings ... 方法似乎保存了默认设置,但它确实创建了一个与您创建的文件同名的新配置文件。或者,您可以执行终端 -> 首选项 -> 配置文件。以名称创建配置文件,然后使用齿轮菜单 => 导出 ... 导出您当前正在使用的配置文件。
  • 如果您在保存名称时更改名称,则会创建另一个配置文件,但它将使用您想要的设置。您甚至可以删除这些配置文件,但是当您运行该命令时,它会自动添加这些配置文件。这一切“如何运作”似乎有很多奇怪之处。
【解决方案5】:

您可以使用以下命令启动终端,不知道如何指定颜色:

 open /Applications/Utilities/Terminal.app/

【讨论】:

  • 对于较新的 OS X 版本,您需要指定“-a”参数来表示应用程序的名称。 "open -n -a /Applications/Utilities/Terminal.app/" 此外,"-n" 参数可能有助于启动新窗口(可选)。
【解决方案6】:

上面@david-moles 的答案有效,但在 ~ 而不是启动 term 的当前工作目录中运行终端和命令。此变体添加了一个 cd 命令。

#!/usr/bin/env bash
# based on answer by @david-moles in 
# https://stackoverflow.com/questions/4404242/programmatically-launch-terminal-app-with-a-specified-command-and-custom-colors
echo "
on run argv
  if length of argv is equal to 0
    set command to \"\"
  else
    set command to item 1 of argv
  end if
  set command to \"cd '"$PWD"' ;\" & command
  if length of argv is greater than 1
    set profile to item 2 of argv
    runWithProfile(command, profile)
  else
    runSimple(command)
  end if
end run

on runSimple(command)
  tell application \"Terminal\"
    activate
    set newTab to do script(command)
  end tell
  return newTab
end runSimple

on runWithProfile(command, profile)
  set newTab to runSimple(command)
  tell application \"Terminal\" to set current settings of newTab to (first settings set whose name is profile)
end runWithProfile
" | osascript - "$@" > /dev/null

可能有一种方法可以使用 applescript 设置 PWD。​​p>

注意:当我使用它时,有时我会使用两个终端窗口,一个是在 ~ 中运行的 shell,另一个是运行 cd 命令和来自 argv[1] 的命令。如果终端尚未运行,似乎会发生;也许它正在打开旧状态(即使我关闭它时没有打开的终端)。

【讨论】:

    猜你喜欢
    • 2015-09-16
    • 2020-01-29
    • 1970-01-01
    • 2020-02-19
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多