Komut satırından yeni Terminal Sekmesi açın (Mac OS X)


116

Şu anda açık olan bir sekmedeki komut satırından Mac OS X'in terminalinde yeni bir sekme açmak mümkün müdür?

Terminal'de yeni bir sekme açmak için klavye kısayolunun "CMD + t" olduğunu biliyorum, ancak komut satırında çalıştırılan betik tabanlı bir çözüm arıyorum.

Yanıtlar:


126

Bunu dene:

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

D'Ah! Yorumunuzu tamamen kaçırdım, google üzerinden benzer bir çözüm buldum. Bir fark: Terminal en öndeki uygulama olmadığı sürece benim için işe yaramadı (10.6.8'de), bu yüzden onu öne zorlamak için "etkinleştir" seçeneğini ekledim.
Gordon Davisson

5
edit: echo helloBu yeni sekmeye nasıl yeni bir komut ekleyebilirim .
ThomasReggi

22
@ThomasReggi: -e 'tell application "Terminal" to do script "echo hello" in selected tab of the front window'osascript komutunun sonuna ekleyin .
Gordon Davisson

2
@clevertension for iTerm it is justopen -a iTerm ~/Applications/
onmyway133

1
@Ciastopiekarz Yeni açılan sekmede mi demek istiyorsunuz? ThomasReggi'ye cevabımla aynı yaklaşımı kullanın: ekleyin -e 'tell application "Terminal" to do script "cd /path/to/target/directory" in selected tab of the front window'. Yol bir değişkenden geliyorsa, tek tırnaklı yerine çift tırnaklı bir dize kullanmanız ve içteki tırnaklı dizeden ve muhtemelen yolun kendisinden kaçmanız gerekeceğini unutmayın .
Gordon Davisson

163

Güncelleme : Bu cevap, aşağıda yayınlanan ve hala OSX 10.10'dan itibaren çalışan kabuk işlevine dayalı olarak popülerlik kazandı ( -gseçenek haricinde ).
Ancak, daha tam özellikli, daha sağlam, test komut versiyonu artık mevcut npm kayıt CLI olarakttab , aynı zamanda destekler iTerm2 :

  • Eğer varsa node.js yüklü, basitçe çalıştırın:

    npm install -g ttab
    

    (Node.js'yi nasıl kurduğunuza bağlı olarak, başa eklemeniz gerekebilir sudo).

  • Aksi takdirde, bu talimatları izleyin .

  • Kurulduktan sonra, ttab -hkısa kullanım bilgileri için veya man ttabkılavuzu görüntülemek için çalıştırın .


Kabul edilen cevaba dayanarak, aşağıda mevcut Terminal penceresinde yeni bir sekme açmak ve isteğe bağlı olarak bir komut çalıştırmak için bir bash kolaylık işlevi verilmiştir (bonus olarak, bunun yerine yeni bir pencere oluşturmak için bir değişken işlev vardır ).

Bir komut belirtilirse, ilk belirteci yeni sekmenin başlığı olarak kullanılacaktır.

Örnek çağrılar:

    # 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

Ikaz : Eğer çalıştırdığınızda newtab(veya newwin) bir komut dosyasından, komut dosyasının ilk çalışma klasörü, yeni sekme / pencerede çalışma klasörü olacak önce komut dosyası içinde çalışan klasörü değiştirmek bile çağrılırken newtab/ newwin- geçmesi evalbir ile cdgeçici bir çözüm olarak komuta (yukarıdaki örneğe bakın).

Kaynak kodu (örneğin, bash profilinize yapıştırın):

# 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.
}

3
@jcollum Memnuniyetle; yararlı bulduğuna sevindim. Gönderiyi bir uyarı yeniden çalışan klasörlerle güncelledim ve ayrıca kodu da güncelledim: ek seçenekler -g(yeni sekme / pencere oluştururken Terminal'i etkinleştirmeyin) ve -G(Terminal'i etkinleştirmeyin ve Terminal içindeki etkin sekmeyi değiştirmeyin ) - örneğin arka planda bir sunucu başlatırken yararlıdır. Bu şekilde yeni bir sekme oluştururken, daha önce etkin olan uygulama yeniden etkinleştirilmeden önce Terminal'in kısa bir süre için etkinleştirilmesi gerektiğini unutmayın.
mklement0

1
@Leonardo Yeni sekme, işlevin çağrıldığı sekmeyle aynı çalışma dizinine sahiptir. Arama yapmadan önce bir komut dosyası içinde farklı bir klasöre geçmek newtabmaalesef işe yaramıyor. Çözüm, komutuyla bir evalifade cdiletmektir newtab; örneğin: newtab eval "cd ~/Library/Application\ Support; ls". Gönderilen tüm komutu çift tırnak evaliçine alın ve içinde ters eğik çizgi kaçışını kullanın.
mklement0

1
@IntegrityFirst: Önerinize göre, işlev imzalarını function newtabve function newwin(ancak, parantez YOK) olarak değiştirdim, böylece işlevleri tanımlarken takma adlarla çarpışmayı önlemek gerekir , ancak çağrı sırasında aynı ada sahip bir takma adın öncelikli olduğunu unutmayın ( takma adı atlayın, ad-hoc, işlev adının herhangi bir bölümünü alıntılayın, örneğin:) \newtab.
mklement0

2
@IntegrityFirst: İşte öğrendiklerim: POSIX <name>() { ... }işlev sözdiziminin kullanılması, bir takma ad tanımlanırsa işlev tanımını bozan (ayrıştırma hatası!) Takma ad genişletmesine<name> tabi kılar . Normalde çağrılan komut dosyalarında diğer ad genişletme varsayılan olarak KAPALI olduğundan, tipik olarak bir sorun değildir. Ancak, INTERACTIVE bir kabuktan KAYNAKLANAN komut dosyalarında - örneğin profil / başlatma dosyalarında - diğer ad genişletmesi açık IS. Düzeltme: Fonksiyonu tanımlamak için POSIX olmayan sözdizimi kullanın - bu durumda takma ad genişletmesine tabi DEĞİLDİR. <name>function <name> { ... }<name>
mklement0

1
Teşekkürler! bu , if [ "${BASH_SOURCE}" == "${0}" ]senaryo olarak çağrılabilmesi için bir case ifadesi ekler (örneğin ): gist.github.com/westurner/01b6be85e5a51fda22a6newtab.shnewwin.sh
Wes Turner

18

Bash_it tarafından şu şekilde yapılır :

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
}

Bunu .bash_profile dosyanıza ekledikten sonra tab, mevcut çalışma dizinini yeni bir sekmede açmak için komutu kullanırsınız.

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


1
Çok yararlı. Bunu .bash_profile dosyamda kullanarak, bir dizi sekme ve bunlara otomatik olarak ssh başlatabiliyorum. Elbette, ssh anahtar çifti kimlik doğrulamasını etkinleştirdim
Sandeep Kanabar

16
osascript -e 'tell app "Terminal"
   do script "echo hello"
end tell'

Bu, yeni bir terminal açar ve içindeki "echo hello" komutunu çalıştırır.


3
Bu işe yaradı, ancak yeni sekme ayrı bir Terminal örneğinde oluşturuldu. Yeni sekme, Terminalimin mevcut örneğinde kalıyor mu?
Calvin Cheng

Bu arada, do script ""bir komut vermeden yeni bir terminal oluşturmak için boş bir dizeyle kullanabilirsiniz.
Chris Sayfa

9

Eğer oh-my-zsh kullanıyorsanız (her popüler geek kullanmalıdır), "osx" eklentisini etkinleştirdikten sonra .zshrc, sadece tabkomutu girin ; yeni bir sekme açar ve cdbulunduğunuz dizinde.


Çok ilginç görünüyor. Zcsh ile geleneksel bash arasındaki fark nedir?
Calvin Cheng

Çok benzerler, ancak en ilginç olanı akıllı, güçlü sekme tamamlama ve otomatik düzeltme özelliğine sahip. Burada iyi karşılaştırmaya bakın . Oh-my-zsh, başlamanıza yardımcı olacak güzel ve kullanışlı ayarlar / eklentiler içeren bir ortam
kuruyor

CharlesB'nin karşılaştırma bağlantısına hızlıca göz attı. Çok ilginç. BPython kabuğu ile iPython kabuğuna benziyor.
Calvin Cheng

zsh kontrolü kaybetmek için daha da eski püskü durumları korumayı başardı
James

Bununla ilgili daha fazla bilgi verebilir misiniz? Sekme komutu nedir? Giriş tabyapmak hiçbir şey yapmıyor gibi görünüyor
Solvitieg

7

Klavye kısayolu cmd-tyeni bir sekme açar, böylece bu tuş vuruşunu OSA komutuna aşağıdaki şekilde geçirebilirsiniz:

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


6

Bunları .bash_profile dosyama ekledim, böylece sekme adına ve yeni sekmeye erişebilirim

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
}

Böylece, belirli bir sekmedeyken yazmanız yeterli

tabname "New TabName"

sahip olduğunuz tüm açık sekmeleri düzenlemek için. Sekmede bilgi alıp orada değiştirmekten çok daha iyidir.


Teşekkürler. sekmeden ssh yaptıktan ve ssh oturumundan çıktıktan sonra sekme adını nasıl koruyacağınızı biliyor musunuz?
anjanb

4

Bunun eski bir gönderi olduğunu biliyorum, ancak bu benim için çalıştı:

open -a Terminal "`pwd`"

Bir komutu aşağıda istendiği gibi çalıştırmak için biraz titreme gerekir:

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

Çok hoş! Terminal'in yeni örneğinde çalışacak komutları iletmek istersem nasıl yaparım? : D
Strazan

@Strazan yukarıdaki cevabı düzenledi ... iyi eğlenceler !! Görünüşe göre terminal böyle bir parametre alacak ...
neophytte

3

bir terminal penceresindeyken, command + n => yeni bir terminal açar ve command + t => mevcut terminal penceresinde yeni bir sekme açar


1
bu komut satırından çalışmalıdır. temelde bir senaryo. çünkü bu tekrarlayan bir görev
Gianfranco P.

2

İTerm kullanıyorsanız, bu komut yeni bir sekme açacaktır:

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

Bunu bir .zshrc veya .bashrc'ye eklemeniz gerekiyorsa, bunu bir takma ad yerine bir işlevle yapabilirsiniz (tüm kaçışlardan dolayı yapmanız gerekecek). stackoverflow.com/a/20111135/1401336
Vigrant

@Andrew Schreiber: Ama kontrol yeni sekmeye geçmiyor. Demek istediğim, yeni sekmeyi açtıktan sonra bir kodunuz varsa, bu kod orijinal sekmede çalıştırılır. Komut dosyasına aşağıdaki komutları yeni sekmede işlemesini söylemenin bir yolu var mı?
Ashwin

1
open -n -a Terminal

ve hedef dizini parametre olarak iletebilirsiniz

open -n -a Terminal /Users

Bu benim için yeni bir pencere açıyor. Sekme değil.
stack-delay

0

Standart bir komut dosyası komutuna (echo) dayanan bu basit parçacığa ne dersiniz?

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

0

X kurulduğunda (örn. Homebrew veya Quartz), basit bir "xterm &" (neredeyse) hile yapar, yeni bir terminal penceresi açar (yine de bir sekme değil).

Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.