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

yammy1688 commented Jan 24, 2014

nice.

@ghost

This comment has been minimized.

Copy link

ghost commented Jun 5, 2014

Super!

@clevertension

This comment has been minimized.

Copy link

clevertension 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

aidanhmiles commented Feb 8, 2015

glorious!

@aidanhmiles

This comment has been minimized.

Copy link

aidanhmiles 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

richadams8 commented Feb 17, 2015

fabulous.

@predorock

This comment has been minimized.

Copy link

predorock 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

felipebernardes commented Jun 29, 2015

Sweet! thank you.

@vitalybe

This comment has been minimized.

Copy link

vitalybe 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

charles-dyfis-net 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

micealgallagher 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

cmer 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

Jackman3005 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

vacas 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

krainboltgreene 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.

@fourdragons

This comment has been minimized.

Copy link

fourdragons commented Oct 21, 2019

$ open -a iTerm .

Sure, just destroy all their hard work. But, thanks!

@brightzheng100

This comment has been minimized.

Copy link

brightzheng100 commented Jan 22, 2020

Somehow it doesn't work so I change a bit to make sure it addresses my needs: to open a tab vertically and run the command.

#!/bin/bash

[ `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"
            activate
            tell current session of current window to set newTab to split vertically with same profile
            tell newTab
                select
                write text "cd \"$cdto\"$cmd"
            end tell 
        end tell
EOF
}

Save it to a file, source it and test it by:

tab echo 123
@newplasticideas

This comment has been minimized.

Copy link

newplasticideas commented Apr 17, 2020

noob question - will this work with zsh too?

@bobthecow

This comment has been minimized.

Copy link
Owner Author

bobthecow commented May 2, 2020

@newplasticideas there are currently bash and fish implementations. it's possible to port this to zsh as well, but if you're going to do that, i'd suggest starting with https://github.com/oh-my-fish/plugin-tab which has been updated more recently and supports a lot more terminals :)

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.