Skip to content

Instantly share code, notes, and snippets.

Embed
What would you like to do?
Open new Terminal tabs from the command line
#!/bin/bash
#
# Open new Terminal tabs from the command line
#
# Author: Justin Hileman (http://justinhileman.com)
#
# Installation:
# Add the following function to your `.bashrc` or `.bash_profile`,
# or save it somewhere (e.g. `~/.tab.bash`) and source it in `.bashrc`
#
# Usage:
# tab Opens the current directory in a new tab
# tab [PATH] Open PATH in a new tab
# tab [CMD] Open a new tab and execute CMD
# tab [PATH] [CMD] ... You can prob'ly guess
# Only for teh Mac users
[ `uname -s` != "Darwin" ] && return
function tab () {
local cmd=""
local cdto="$PWD"
local args="$@"
if [ -d "$1" ]; then
cdto=`cd "$1"; pwd`
args="${@:2}"
fi
if [ -n "$args" ]; then
cmd="; $args"
fi
osascript &>/dev/null <<EOF
tell application "iTerm"
tell current terminal
launch session "Default Session"
tell the last session
write text "cd \"$cdto\"$cmd"
end tell
end tell
end tell
EOF
}
# Open new iTerm and Terminal tabs from the command line
#
# Author: Justin Hileman (http://justinhileman.com)
#
# Usage:
# tab Opens the current directory in a new tab
# tab [PATH] Open PATH in a new tab
# tab [CMD] Open a new tab and execute CMD
# tab [PATH] [CMD] ... You can prolly guess
function tab -d "Open the current directory in a new tab"
set -l cmd ""
set -l cdto (pwd)
if test (count $argv) -gt 0
pushd . >/dev/null
if test -d $argv[1]
cd $argv[1]
set cdto (pwd)
set -e argv[1]
end
popd >/dev/null
end
if test (count $argv) -gt 0
set cmd "; $argv"
end
switch $TERM_PROGRAM
case 'iTerm.app'
osascript 2>/dev/null -e "
tell application \"iTerm\"
tell current terminal
launch session \"Default Session\"
tell the last session
write text \"cd \\\"$cdto\\\"$cmd\"
end tell
end tell
end tell
"
case 'Apple_Terminal'
osascript 2>/dev/null -e "
tell application \"Terminal\"
activate
tell application \"System Events\" to keystroke \"t\" using command down
repeat while contents of selected tab of window 1 starts with linefeed
delay 0.01
end repeat
do script \"cd \\\"$cdto\\\"$cmd\" in window 1
end tell
"
case '*'
echo "Unknown terminal: $TERM_PROGRAM" >&2
end
end
@yammy1688

This comment has been minimized.

Copy link

commented Jan 24, 2014

nice.

@ghost

This comment has been minimized.

Copy link

commented Jun 5, 2014

Super!

@clevertension

This comment has been minimized.

Copy link

commented Oct 10, 2014

the bash execution from function seem disabled, because of latest shellshock
https://shellshocker.net/

@aidanhmiles

This comment has been minimized.

Copy link

commented Feb 8, 2015

glorious!

@aidanhmiles

This comment has been minimized.

Copy link

commented Feb 10, 2015

does this allow for multiple commands to be executed in a newly opened tab? as in
tab [CMD1] && [CMD2 also executed in same shell as CMD1]

UPDATE: just kidding; passing multiple commands concatenated as one long string works just fine.

@richadams8

This comment has been minimized.

Copy link

commented Feb 17, 2015

fabulous.

@predorock

This comment has been minimized.

Copy link

commented Jun 3, 2015

Very cool, there is a way to split in multiple tabs in the same term (i am using iTerm) ??

@felipebernardes

This comment has been minimized.

Copy link

commented Jun 29, 2015

Sweet! thank you.

@vitalybe

This comment has been minimized.

Copy link

commented Feb 23, 2016

Doesn't work with the nightly versions of iTerm2, forked and updated it to work: https://gist.github.com/vitalybe/021d2aecee68178f3c52

@charles-dyfis-net

This comment has been minimized.

Copy link

commented Jun 10, 2016

Dangerously buggy if passed a multi-argument list -- you wouldn't want to tab ls /tmp/* if you weren't 100% certain that there didn't exist a file created with touch '/tmp/$(rm -rf $HOME)' -- and also has issues with arguments with spaces and quotes. First commented the below on vitalybe's fork, but it's relevant here too:


printf -v args '%q ' "$@", if you want to generate your arguments in eval-safe form. Otherwise, you're inviting bugs -- local args="$@" flattens the original array into a string, and a string can't store array boundaries in a safe way without escaping.

To provide an example:

$ set -- "first arg" "second arg" "third arg"
$ args_flat="$@"
$ args_arr=( "$@" )
$ declare -p args_flat args_arr
declare -- args_flat="first arg second arg third arg"
declare -a args_arr='([0]="first arg" [1]="second arg" [2]="third arg")'

Now, if your goal is an eval-safe string, that would look like this:

$ printf -v args_str '%q ' "$@"
$ declare -p args_str
declare -- args_str="first\\ arg second\\ arg third\\ arg "

What this did is generate a chunk of script which, if parsed by a shell, will evaluate back to its original inputs -- with first arg, second arg, and third arg each still recognized as separate words. This is thus something you could safely append to cmd.

@micealgallagher

This comment has been minimized.

Copy link

commented Oct 12, 2016

Dude, this is exactly what I was looking for. Thank-you!

@andrialexandrou

This comment has been minimized.

@cmer

This comment has been minimized.

Copy link

commented May 26, 2017

I'm getting this, any idea?

~/dotfiles ☀️  ✖ 1 $ tab ls
58:66: syntax error: Expected end of line but found identifier. (-2741)
@Jackman3005

This comment has been minimized.

Copy link

commented Jan 8, 2018

@cmer

Looks like a newer version of osascript or iterm has caused this error. I found the updated syntax to use on iterms site which has given me this updated code. Cheers.

# needed to use exit instead of return
[ `uname -s` != "Darwin" ] && echo "Cannot run on non-macosx system." && exit

function tab () {
    local cmd=""
    local cdto="$PWD"
    local args="$@"

    if [ -d "$1" ]; then
        cdto=`cd "$1"; pwd`
        args="${@:2}"
    fi

    if [ -n "$args" ]; then
        cmd="$args"
    fi

    osascript -i <<EOF
        tell application "iTerm"
            tell current window
                create tab with default profile
                tell the current session
                    write text "cd \"$cdto\"; $cmd"
                end tell
            end tell
        end tell
EOF
}

tab "echo hello"
@vacas

This comment has been minimized.

Copy link

commented Feb 21, 2018

@Jackman3005,

Thanks for the update! The code worked, but I was having trouble running the command (i.e. cmd). Made changes to my code, in case anyone else wants to use it (am using iTerm2):

function tab () {
    local cdto="$PWD"
    local args="$@"

    if [ -d "$1" ]; then
        cdto=`cd "$1"; pwd`
        args="${@:2}"
    fi

    osascript -i <<EOF
        tell application "iTerm2"
                tell current window
                        create tab with default profile
                        tell the current session
                                write text "cd \"$cdto\" && $args"
                        end tell
                end tell
        end tell
EOF
}

Cheers!

@krainboltgreene

This comment has been minimized.

Copy link

commented Apr 14, 2019

As of at least macos Mojave, iTerm 3.2.8, if you run:

$ open -a iTerm .

It will add it as a tab to the current window.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
You can’t perform that action at this time.