【问题标题】:Running a command in a new Mac OS X Terminal window在新的 Mac OS X 终端窗口中运行命令
【发布时间】:2009-06-12 22:26:28
【问题描述】:

我一直试图弄清楚如何在新的 Max OS X Terminal.app 窗口中运行 bash 命令。例如,以下是我在新的 bash 进程中运行命令的方式:

bash -c "my command here"

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

Terminal.app -c "my command here"

但这当然行不通。我知道“open -a Terminal.app”命令,但我看不到如何将参数转发到终端,或者即使我做了要使用的参数。

【问题讨论】:

  • 您可以随时打开首选项,转到“配置文件”选项卡,进入“Shell”页面并在那里设置启动命令。它仅在应用程序打开时运行,但它比 hacky 替代品更好!
  • 在超级用户superuser.com/q/174576/122841也看到同样的问题

标签: macos bash terminal


【解决方案1】:

我能想到的一种方法是创建一个 .command 文件并像这样运行它:

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

或使用applescript:

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

虽然你要么必须转义很多双引号,要么不能使用单引号

【讨论】:

  • 我决定采用第一种方法。这是相当hack-ish,但它有效,我不必担心在我的命令或任何东西中转义引号。谢谢。
  • 如果命令需要参数化运行,也许你会想要交换单引号和双引号;尽管您需要了解差异才能正确执行此操作。 osascript -e "tell application \"Terminal\" to do script \"echo '$variable'\"'
  • 有人知道如何关闭愚蠢的终端窗口吗?
  • 在 shell 脚本命令的末尾添加; exit,如do script "echo hello; exit"。您仍然需要单独关闭窗口。
【解决方案2】:

部分解决方案:

把你想做的事情放在一个shell脚本中,像这样

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

并且不要忘记'chmod +x file' 使其可执行。然后就可以了

open -a Terminal.app scriptfile

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

【讨论】:

  • 新打开的窗口的上下文似乎是用户的根文件夹/Users/{username}。有什么方法可以使上下文文件夹与打开它的父终端窗口相同?
  • > 虽然你可能需要弄清楚如何加载用户的 rc 文件和东西.. 使用 bash -l 来完成这个
【解决方案3】:

我一直在尝试这样做。这是一个脚本,它会切换到相同的工作目录,运行命令,然后关闭终端窗口。

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

【讨论】:

  • 不喜欢接受的脚本,你的解决当前目录问题。谢谢!
  • 很好的解决方案;不过,它会在 launching shell 中将 tab 1 of window id 7433 之类的内容输出到标准输出。要抑制这种情况,请将&gt;/dev/null before &lt;&lt;END.
  • 这不会固有地关闭终端窗口。它只是退出命令解释器。 Terminal.app 必须配置为自动关闭窗口,或在命令解释器干净退出时关闭。
【解决方案4】:

如果有人关心,这里是 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

【讨论】:

    【解决方案5】:

    这里还有另一种看法(也使用 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' 
    

    参见:coden-ps.joyent.com/posts/show/1516

    【讨论】:

    • 这是唯一对我有用的。我的需要是我需要运行一个命令来创建一个到机器的 ssh 隧道,然后我想打开一个 vncloc 来屏幕共享它。我可以通过 3 个步骤在新的 bash 函数中完美地做到这一点:在新窗口中执行隧道命令,休眠 3 秒,然后在原始窗口中打开 vncloc。完美运行。
    【解决方案6】:

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

    【讨论】:

      【解决方案7】:

      我做了一个奥斯卡答案的函数版,这个也是复制环境和修改到相应的目录

      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
      

      【讨论】:

      • 如果您同时启动多个进程,TMP_FILE="tmp.command" 行可能会出现问题。我建议将其替换为TMP_FILE=$(mktemp "/tmp/command.XXXXXX")
      【解决方案8】:

      一位同事问我如何一次打开很多 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 完成得太快,在启动的会话有机会读取文件之前执行陷阱以删除临时目录(由 mktemp 创建)。

      【讨论】:

        【解决方案9】:

        我称这个脚本为 trun。我建议将它放在可执行路径中的目录中。确保它可以像这样执行:

        chmod +x ~/bin/trun
        

        然后你可以在新窗口中运行命令,只需在它们之前添加 trun,如下所示:

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

        这是脚本。它做了一些花哨的事情,比如传递你的参数,更改标题栏,清除屏幕以消除 shell 启动混乱,完成后删除它的文件。通过为每个新窗口使用一个唯一的文件,它可用于同时创建多个窗口。

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

        【讨论】:

        • $* 的错误使用将破坏输入中任何重要的引用。你想要"$@"
        • 我正在寻找open -b com.apple.terminal。谢谢
        【解决方案10】:

        这里需要的另一个选项是“ttab

        https://www.npmjs.com/package/ttab

        安装
        npm install ttab -g
        
        用法:打开另一个标签并运行ls
        ttab ls
        
        用法 2:在 ~/dev 目录中打开新标签页,带有绿色 BG,标题为“hi”,然后运行 ​​code .
        ttab -s Grass -t hi -d '~/dev' code .
        

        【讨论】:

          【解决方案11】:

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

          【讨论】:

          • 知道当然有用,但我需要以编程方式进行。让我的程序生成一个 .command 文件然后打开它是一个合理的(如果有点 hackish)解决方案。
          猜你喜欢
          • 2014-07-25
          • 2023-03-21
          • 2022-06-10
          • 2023-03-27
          • 2011-11-02
          • 2016-01-10
          • 1970-01-01
          • 1970-01-01
          • 2013-03-10
          相关资源
          最近更新 更多