从命令行打开新的终端选项卡 (Mac OS X)

问题描述 投票:0回答:15

是否可以从当前打开的选项卡中的命令行在 Mac OS X 终端中打开新选项卡?

我知道在终端中打开新选项卡的键盘快捷键是“CMD+t”,但我正在寻找在命令行中执行的基于脚本的解决方案。

macos tabs terminal
15个回答
177
投票

更新

  • 这个答案基于下面发布的 shell 函数而受到欢迎,该函数在 macOS Sonoma (14.x) 上仍然有效(除了

    -g
    选项)。
    然而,功能更齐全、更强大、经过测试的脚本版本(独立CLI)现在可以在npm注册表作为CLI
    ttab
    获得,还支持iTerm2并且,在 Linux 发行版上,gnome-terminal:

  • 如果您安装了 Node.js,只需运行(根据您安装 Node.js 的方式,您可能需要添加

    sudo
    ):

    npm install -g ttab
    
  • 否则,请按照这些说明

  • 安装后,运行

    ttab -h
    获取简洁的使用信息,或运行
    man ttab
    查看手册。


基于已接受的答案,下面是一个 bash 便利函数

newtab
,用于在当前终端窗口中打开一个新选项卡并可选择执行命令(作为奖励,有一个用于创建新 窗口的变体函数 相反,
newwin
)。

如果指定了命令,则其第一个标记将用作新选项卡的标题。

调用示例:

    # Get command-line help.
newtab -h
    # Simpy open new tab.
newtab
    # Open new tab and execute command (quoted parameters are supported).
newtab ls -l "$Home/Library/Application Support"
    # Open a new tab with a given working directory and execute a command;
    # Double-quote the command passed to `eval` and use backslash-escaping inside.
newtab eval "cd ~/Library/Application\ Support; ls"
    # Open new tab, execute commands, close tab.
newtab eval "ls \$HOME/Library/Application\ Support; echo Press a key to exit.; read -s -n 1; exit"
    # Open new tab and execute script.
newtab /path/to/someScript
    # Open new tab, execute script, close tab.
newtab exec /path/to/someScript

源代码(例如,粘贴到您的 bash 配置文件中):

# Opens a new tab in the current Terminal window and optionally executes a command.
# When invoked via a function named 'newwin', opens a new Terminal *window* instead.
function newtab {

    # If this function was invoked directly by a function named 'newwin', we open a new *window* instead
    # of a new tab in the existing window.
    local funcName=$FUNCNAME
    local targetType='tab'
    local targetDesc='new tab in the active Terminal window'
    local makeTab=1
    case "${FUNCNAME[1]}" in
        newwin)
            makeTab=0
            funcName=${FUNCNAME[1]}
            targetType='window'
            targetDesc='new Terminal window'
            ;;
    esac

    # Command-line help.
    if [[ "$1" == '--help' || "$1" == '-h' ]]; then
        cat <<EOF
Synopsis:
    $funcName [-g] [command [param1 ...]]

Description:
    Opens a $targetDesc and optionally executes a command.

    The new $targetType will run a login shell (i.e., load the user's shell profile) and inherit
    the working folder from this shell (the active Terminal tab).

    -g (back*g*round) causes Terminal not to activate, but within Terminal, the new tab/window
      will become the active element.

    NOTE: With -g, for technical reasons, Terminal will still activate *briefly* when
    you create a new tab (creating a new window is not affected).

    When a command is specified, its first token will become the new ${targetType}'s title.
    Quoted parameters are handled properly.

    To specify multiple commands, use 'eval' followed by a single, *double*-quoted string
    in which the commands are separated by ';' Do NOT use backslash-escaped double quotes inside
    this string; rather, use backslash-escaping as needed.
    Use 'exit' as the last command to automatically close the tab when the command
    terminates; precede it with 'read -s -n 1' to wait for a keystroke first.

    Alternatively, pass a script name or path; prefix with 'exec' to automatically
    close the $targetType when the script terminates.

Examples:
    $funcName ls -l "\$Home/Library/Application Support"
    $funcName eval "ls \\\$HOME/Library/Application\ Support; echo Press a key to exit.; read -s -n 1; exit"
    $funcName /path/to/someScript
    $funcName exec /path/to/someScript
EOF
        return 0
    fi

    # Option-parameters loop.
    inBackground=0
    while (( $# )); do
        case "$1" in
            -g)
                inBackground=1
                ;;
            --) # Explicit end-of-options marker.
                shift   # Move to next param and proceed with data-parameter analysis below.
                break
                ;;
            -*) # An unrecognized switch.
                echo "$FUNCNAME: PARAMETER ERROR: Unrecognized option: '$1'. To force interpretation as non-option, precede with '--'. Use -h or --h for help." 1>&2 && return 2
                ;;
            *)  # 1st argument reached; proceed with argument-parameter analysis below.
                break
                ;;
        esac
        shift
    done

    # All remaining parameters, if any, make up the command to execute in the new tab/window.

    local CMD_PREFIX='tell application "Terminal" to do script'

        # Command for opening a new Terminal window (with a single, new tab).
    local CMD_NEWWIN=$CMD_PREFIX    # Curiously, simply executing 'do script' with no further arguments opens a new *window*.
        # Commands for opening a new tab in the current Terminal window.
        # Sadly, there is no direct way to open a new tab in an existing window, so we must activate Terminal first, then send a keyboard shortcut.
    local CMD_ACTIVATE='tell application "Terminal" to activate'
    local CMD_NEWTAB='tell application "System Events" to keystroke "t" using {command down}'
        # For use with -g: commands for saving and restoring the previous application
    local CMD_SAVE_ACTIVE_APPNAME='tell application "System Events" to set prevAppName to displayed name of first process whose frontmost is true'
    local CMD_REACTIVATE_PREV_APP='activate application prevAppName'
        # For use with -G: commands for saving and restoring the previous state within Terminal
    local CMD_SAVE_ACTIVE_WIN='tell application "Terminal" to set prevWin to front window'
    local CMD_REACTIVATE_PREV_WIN='set frontmost of prevWin to true'
    local CMD_SAVE_ACTIVE_TAB='tell application "Terminal" to set prevTab to (selected tab of front window)'
    local CMD_REACTIVATE_PREV_TAB='tell application "Terminal" to set selected of prevTab to true'
    local CMD_SETTITLE
    local quotedArgs
    local cmd
    local cmdArgsArray=()
    local setTitleArgsArray=()

    if (( $# )); then # Command specified; open a new tab or window, then execute command.
            # Use the command's first token as the tab title.
        local tabTitle=$1
        case "$tabTitle" in
            exec|eval) # Use following token instead, if the 1st one is 'eval' or 'exec'.
                tabTitle=$(echo "$2" | awk '{ print $1 }') 
                ;;
            cd) # Use last path component of following token instead, if the 1st one is 'cd'
                tabTitle=$(basename "$2")
                ;;
        esac
        CMD_SETTITLE="tell application \"Terminal\" to set custom title of front window to \"$tabTitle\""
        setTitleArgsArray=('-e' "$CMD_SETTITLE")
    fi
    # Formulate an escaped form of the command to execute in the new tab.
    # Note: A command is *implicitly* used in *script* use, namely a `cd` command
    #       to ensure that the new tab inherits the script's working dir. reliably.
        # The tricky part is to quote the command tokens properly when passing them to AppleScript:
        # Step 1: Quote all parameters (as needed) using printf '%q' - this will perform backslash-escaping.
    # Start with a `cd` command in *script* (non-interactive) use.
    [[ -z $PS1 ]] && quotedArgs="cd -- $(printf '%q' "$PWD")"
    [[ -n $quotedArgs && $# -gt 0 ]] && quotedArgs+=' && '
    # Append the user-specific command, if any.
    (( $# )) && quotedArgs+=$(printf '%q ' "$@")
        # Step 2: Escape all backslashes again (by doubling them), because AppleScript expects that.
    cmd="$CMD_PREFIX \"${quotedArgs//\\/\\\\}\""
    # cmd="$CMD_PREFIX \"${quotedArgs}\""
        # Open new tab or window, execute command, and assign tab title.
        # '>/dev/null' suppresses AppleScript's output when it creates a new tab.
    if (( makeTab )); then
        [[ -n $quotedArgs ]] && cmdArgsArray=('-e' "$cmd in front window")
        if (( inBackground )); then
            osascript -e "$CMD_SAVE_ACTIVE_APPNAME" -e "$CMD_ACTIVATE" -e "$CMD_NEWTAB" "${cmdArgsArray[@]}" "${setTitleArgsArray[@]}" -e "$CMD_REACTIVATE_PREV_APP" >/dev/null
        else
            osascript -e "$CMD_ACTIVATE" -e "$CMD_NEWTAB" "${cmdArgsArray[@]}" "${setTitleArgsArray[@]}" >/dev/null
        fi
    else # make *window*

        # Note: $CMD_NEWWIN by itself implicitly creates a new window.
        [[ -n $quotedArgs ]] && cmdArgsArray=('-e' "$cmd") || cmdArgsArray=('-e' "$CMD_NEWWIN")
        if (( inBackground )); then
            osascript "${cmdArgsArray[@]}" "${setTitleArgsArray[@]}" >/dev/null
        else
                # Note: Even though we do not strictly need to activate Terminal first, we do it, as assigning the custom title to the 'front window' would otherwise sometimes target the wrong window.
            osascript -e "$CMD_ACTIVATE" "${cmdArgsArray[@]}" "${setTitleArgsArray[@]}" >/dev/null
        fi
    fi        

}

# Opens a new Terminal window and optionally executes a command.
function newwin {
    newtab "$@" # Simply pass through to 'newtab', which will examine the call stack to see how it was invoked.
}

148
投票

试试这个:

osascript -e 'tell application "Terminal" to activate' \
  -e 'tell application "System Events" to tell process "Terminal" to keystroke "t" using command down' \
  -e 'tell application "Terminal" to do script "echo hello" in selected tab of the front window'

但是如果您需要运行动态命令,请设置

myCommand 
变量,并将最后一行替换为:

-e "tell application \"Terminal\" to do script \"${myCommand};\" in selected tab of the front window";

25
投票
osascript -e 'tell app "Terminal"
   do script "echo hello"
end tell'

这将打开一个新终端并在其中执行命令“echo hello”。


20
投票

这就是 bash_it 的实现方法:

function tab() {
  osascript 2>/dev/null <<EOF
    tell application "System Events"
      tell process "Terminal" to keystroke "t" using command down
    end
    tell application "Terminal"
      activate
      do script with command "cd \"$PWD\"; $*" in window 1
    end tell
EOF
}

将其添加到 .bash_profile 后,您可以使用

tab
命令在新选项卡中打开当前工作目录。

参见: https://github.com/revans/bash-it/blob/master/plugins/available/osx.plugin.bash#L3


18
投票

如果你使用oh-my-zsh(每个时尚极客都应该使用),在激活.zshrc中的

macos
插件后,只需输入
tab
命令即可;它将打开一个新选项卡,并在您所在的目录中打开
cd


8
投票

我将这些添加到我的 .bash_profile 中,这样我就可以访问 tabname 和 newtab

tabname() {
  printf "\e]1;$1\a"
}

new_tab() {
  TAB_NAME=$1
  COMMAND=$2
  osascript \
    -e "tell application \"Terminal\"" \
    -e "tell application \"System Events\" to keystroke \"t\" using {command down}" \
    -e "do script \"printf '\\\e]1;$TAB_NAME\\\a'; $COMMAND\" in front window" \
    -e "end tell" > /dev/null
}

因此,当您在特定选项卡上时,您只需键入

tabname "New TabName"

整理您所有打开的选项卡。这比在选项卡上获取信息要好得多 在那里改变它。


8
投票

我知道这是一篇旧帖子,但这对我有用:

open -a Terminal "`pwd`"

要按照下面的要求运行命令需要一些技巧:

echo /sbin/ping 8.8.8.8 > /tmp/tmp.sh;chmod a+x /tmp/tmp.sh;open -a Terminal /tmp/tmp.sh

6
投票

键盘快捷键

cmd-t
打开一个新选项卡,因此您可以将此按键传递给 OSA 命令,如下所示:

osascript -e 'tell application "System Events"' -e 'keystroke "t" using command down' -e 'end tell'


3
投票
open -n -a Terminal

您可以将目标目录作为参数传递

open -n -a Terminal /Users

2
投票

当您在终端窗口中时, command + n => 打开一个新终端并 command + t => 在当前终端窗口中打开一个新选项卡


1
投票

如果您使用iTerm,此命令将打开一个新选项卡:

osascript -e 'tell application "iTerm" to activate' -e 'tell application "System Events" to tell process "iTerm" to keystroke "t" using command down'

0
投票

这个基于标准脚本命令(echo)的简单片段怎么样:

# set mac osx's terminal title to "My Title"
echo -n -e "\033]0;My Title\007"

0
投票

安装了 X(例如,从自制程序或 Quartz),一个简单的“xterm &”就(几乎)完成了任务,它打开了一个新的终端窗口(尽管不是选项卡)。


0
投票

我制作了一个简化版本,可以解决生成新 UI 的 AppleScript bug。

on run argv
    set scpt to first item in argv
    set flag to application "Terminal" is not running
    tell application "Terminal"
        do script scpt
        activate
        delay 1.0E-5
        if flag then close back window
    end tell
end run

或者这也有效

open -a Terminal.app path/file.sh

0
投票

另一个选择是使用

make
更好地组织终端选项卡的启动。例如,您可以创建一个如下所示的 make 文件:

Makefile

.PHONY:launchtabgroup1
launchtabgroup1:
    chmod u+r+x scripts/launch_tabgroup1.sh
    scripts/launch_tabgroup1.sh

.PHONY:launchtabgroup2
launchtabgroup2:
    chmod u+r+x scripts/launch_tabgroup2.sh
    scripts/launch_tabgroup2.sh

然后在存储 make 文件的子目录中创建一个脚本目录,其中包含打开该组所需的任何选项卡的所有命令。像这样:

launch_tabgroup1.sh

#!/usr/bin/env sh


osascript -e 'tell application "Terminal" to activate' \
  -e 'tell application "System Events" to tell process "Terminal" to keystroke "t" using command down' \
  -e 'tell application "Terminal" to do script "cd ../path/to/desired/directory" in selected tab of the front window'

osascript -e 'tell application "Terminal" to activate' \
  -e 'tell application "System Events" to tell process "Terminal" to keystroke "t" using command down' \
  -e 'tell application "Terminal" to do script "cd ../path/to/desired/directory" in selected tab of the front window'

osascript -e 'tell application "Terminal" to activate' \
  -e 'tell application "System Events" to tell process "Terminal" to keystroke "t" using command down' \
  -e 'tell application "Terminal" to do script "cd ../path/to/desired/directory" in selected tab of the front window'

您将在 Makefile 中创建相应的条目,调用相应的 .sh 文件,从而启动组中的选项卡!

要实际启动选项卡组,请导航到 Makefile 目录并运行

make launchtabgroup1
make launchtabgroup2

© www.soinside.com 2019 - 2024. All rights reserved.