从命令行打开新的终端选项卡(MacOSX)

是否可以从命令行在当前打开的选项卡中在 MacOSX 的终端中打开一个新的选项卡?

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

136952 次浏览
osascript -e 'tell app "Terminal"
do script "echo hello"
end tell'

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

如果你使用 天啊(每个时髦的极客都应该使用) ,在激活 .zshrc中的 Macos插件之后,只需输入 tab命令; 它会在你所在的目录中打开一个新的选项卡和 cd

试试这个:

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

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

更新 : 这个答案基于下面发布的 shell 函数而变得流行起来,这个函数在 OSX 10.10时仍然可以工作(除了 -g选项)。
然而,一个 更加功能齐全,更加健壮,经过测试的版本现在是 可以在以 CLI ttab的形式在 < a href = “ https://www.npmjs.com/package/ttab”rel = “ noReferrer”> npm Registry 获得,即 也支持 iTerm2 :

  • 如果已经安装了 Node.js,只需运行:

    npm install -g ttab
    

    (取决于您如何安装 Node.js,您可能必须预先设置 sudo)。

  • 否则,按照 这些指示

  • 一旦安装,运行 ttab -h获取简明的使用信息,或者运行 man ttab查看手册。


在公认答案的基础上,下面是一个 bash 方便功能,用于在当前 Terminal 窗口中打开一个新的选项卡并可选地执行一个命令(另外,还有一个用于创建新的 窗户的变体函数)。

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

调用示例:

    # 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
# Open new tab and execute script, but don't activate the new tab.
newtab -G /path/to/someScript

警告 : 当你从一个脚本运行 newtab(或者 newwin)时,脚本的 首字母缩写工作文件夹将是新标签/窗口中的工作文件夹,即使您之前更改了脚本中的工作文件夹调用 newtab/newwin-pass eval并使用 cd命令作为解决方案(见上面的例子)。

源代码(例如,粘贴到 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|-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).
IMPORTANT: In scripts, \`$funcName\` *statically* inherits the working folder from the
*invoking Terminal tab* at the time of script *invocation*, even if you change the
working folder *inside* the script before invoking \`$funcName\`.


-g (back*g*round) causes Terminal not to activate, but within Terminal, the new tab/window
will become the active element.
-G causes Terminal not to activate *and* the active element within Terminal not to change;
i.e., the previously active window and tab stay active.


NOTE: With -g or -G specified, 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
;;
-G)
inBackground=2
;;
--) # 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'


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
local CMD_SETTITLE="tell application \"Terminal\" to set custom title of front window to \"$tabTitle\""
# 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.
local quotedArgs=$(printf '%q ' "$@")
# Step 2: Escape all backslashes again (by doubling them), because AppleScript expects that.
local 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
if (( inBackground )); then
# !! Sadly, because we must create a new tab by sending a keystroke to Terminal, we must briefly activate it, then reactivate the previously active application.
if (( inBackground == 2 )); then # Restore the previously active tab after creating the new one.
osascript -e "$CMD_SAVE_ACTIVE_APPNAME" -e "$CMD_SAVE_ACTIVE_TAB" -e "$CMD_ACTIVATE" -e "$CMD_NEWTAB" -e "$cmd in front window" -e "$CMD_SETTITLE" -e "$CMD_REACTIVATE_PREV_APP" -e "$CMD_REACTIVATE_PREV_TAB" >/dev/null
else
osascript -e "$CMD_SAVE_ACTIVE_APPNAME" -e "$CMD_ACTIVATE" -e "$CMD_NEWTAB" -e "$cmd in front window" -e "$CMD_SETTITLE" -e "$CMD_REACTIVATE_PREV_APP" >/dev/null
fi
else
osascript -e "$CMD_ACTIVATE" -e "$CMD_NEWTAB" -e "$cmd in front window" -e "$CMD_SETTITLE" >/dev/null
fi
else # make *window*
# Note: $CMD_NEWWIN is not needed, as $cmd implicitly creates a new window.
if (( inBackground )); then
# !! Sadly, because we must create a new tab by sending a keystroke to Terminal, we must briefly activate it, then reactivate the previously active application.
if (( inBackground == 2 )); then # Restore the previously active window after creating the new one.
osascript -e "$CMD_SAVE_ACTIVE_WIN" -e "$cmd" -e "$CMD_SETTITLE" -e "$CMD_REACTIVATE_PREV_WIN" >/dev/null
else
osascript -e "$cmd" -e "$CMD_SETTITLE" >/dev/null
fi
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" -e "$cmd" -e "$CMD_SETTITLE" >/dev/null
fi
fi
else    # No command specified; simply open a new tab or window.
if (( makeTab )); then
if (( inBackground )); then
# !! Sadly, because we must create a new tab by sending a keystroke to Terminal, we must briefly activate it, then reactivate the previously active application.
if (( inBackground == 2 )); then # Restore the previously active tab after creating the new one.
osascript -e "$CMD_SAVE_ACTIVE_APPNAME" -e "$CMD_SAVE_ACTIVE_TAB" -e "$CMD_ACTIVATE" -e "$CMD_NEWTAB" -e "$CMD_REACTIVATE_PREV_APP" -e "$CMD_REACTIVATE_PREV_TAB" >/dev/null
else
osascript -e "$CMD_SAVE_ACTIVE_APPNAME" -e "$CMD_ACTIVATE" -e "$CMD_NEWTAB" -e "$CMD_REACTIVATE_PREV_APP" >/dev/null
fi
else
osascript -e "$CMD_ACTIVATE" -e "$CMD_NEWTAB" >/dev/null
fi
else # make *window*
if (( inBackground )); then
# !! Sadly, because we must create a new tab by sending a keystroke to Terminal, we must briefly activate it, then reactivate the previously active application.
if (( inBackground == 2 )); then # Restore the previously active window after creating the new one.
osascript -e "$CMD_SAVE_ACTIVE_WIN" -e "$CMD_NEWWIN" -e "$CMD_REACTIVATE_PREV_WIN" >/dev/null
else
osascript -e "$CMD_NEWWIN" >/dev/null
fi
else
# Note: Even though we do not strictly need to activate Terminal first, we do it so as to better visualize what is happening (the new window will appear stacked on top of an existing one).
osascript -e "$CMD_ACTIVATE" -e "$CMD_NEWWIN" >/dev/null
fi
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.
}

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

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

当你在一个终端窗口, 命令 + n = > 打开一个新的终端,然后 命令 + t = > 在当前终端窗口中打开一个新的选项卡

我将它们添加到我的. 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"

组织所有打开的标签页。这比在标签页上获取信息要好得多 在那里改变。

快捷键 cmd-t会打开一个新的选项卡,这样你就可以像下面这样将这个按键传递给 OSA 命令:

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

在安装了 X 之后(例如从自制程序或 Quartz) ,一个简单的“ xterm &”(几乎)就可以完成这个任务,它会打开一个新的终端窗口(不过不是标签)。

如果您使用的是 项目,这个命令将打开一个新的选项卡:

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

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

open -n -a Terminal /Users

我知道这是一个老职位,但这为我工作:

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

我做了一个简化版本,围绕 AppleScript 错误工作,生成一个新的 UI。

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