OS X Terminal.app : 현재 탭과 동일한 디렉토리에서 새 탭을 시작하는 방법은 무엇입니까?


24

현재 탭이 오래 실행되는 프로세스에 의해 점유되는 동안 다른 작업을 수행하려면 현재 탭과 동일한 디렉토리에서 새 탭을 자주 열어야합니다. 그러나 새 탭을 만들 때 기본적으로 Terminal.app는 ~ /에서 시작합니다. 자동 점프를 만드는 방법에 대한 아이디어가 있습니까?


많은 빠른 응답에 감사드립니다! 스크립트를 호출하여 새 탭을 시작해도 괜찮지 만 이미 실행중인 프로그램이 있고 현재 탭을 차지하고있는 스크립트가 있으면 스크립트를 실행할 수 없기 때문에 다른 방법이 있는지 궁금합니다. |
Riobard

답변:


10

OS X 10.7 (Lion)에서 Terminal.app는이를 기본적으로 지원합니다. New Windows/Tabs open in: Same working directory


애플이 백 포트를하지 않는 것은 너무 나쁘다. Snow Leopard에서이 기능을보고 싶다.
방황 Nauta

4
나는 그것을 설정했지만 나를 위해 작동하지 않습니다. 환경 설정 창은 이것이 작동하기 전에 이스케이프 시퀀스를 활성화하는 것에 대해 알려줍니다.
ramonrails 2013

2

다른 환경을 통해 문자열을 전달할 때는 매우주의해야합니다.

10.4를 실행하므로 'tfork'스크립트가 항상 새 창을 엽니 다. 탭을 사용하도록 쉽게 적응할 수 있어야합니다.

#!/bin/sh

# source: http://www.pycs.net/bob/weblog/2004/02/23.html#P49
# Rewritten to use osascript args -> run handler args.
# Added ability to pass additional initial command and args to new shell.
#    Bug: Non ASCII characters are unreliable on Tiger.
#         Tiger's osascript seems to expect args to be encoded in
#         the system's primary encoding (e.g. MacRoman).
#         Once in AppleScript, they are handled OK. Terminal sends them
#         back to the shell as UTF-8.

test $# -eq 0 && set -- : # default command if none given
osascript - "$(pwd)" "$@" <<\EOF
on run args
  set dir to quoted form of (first item of args)
  set cmd_strs to {}
  repeat with cmd_str in rest of args
    set end of cmd_strs to quoted form of cmd_str
  end
  set text item delimiters to " "
  set cmd to cmd_strs as Unicode text
  tell app "Terminal" to do script "cd " & dir & " && " & cmd
end
EOF

예: tfork git log -p ..FETCH_HEAD


수정 : 이미 실행중인 프로세스의 cwd가 터미널 탭을 “점유”

“현재 탭을 점유하는 프로그램의 현재 디렉토리”라는 아이디어는 예상만큼 명확하지 않습니다.

터미널 탭에는 실행되는 프로세스 (처음에는 쉘, 이후에는 쉘이 시작되는 모든 프로세스)에서 사용하는 단일 tty 장치가 있습니다.

각 (정상) 터미널 tty에는 tty를 "점유"하는 것으로 간주 될 수있는 단일 포 그라운드 프로세스 그룹이 있습니다.

각 프로세스 그룹에는 여러 프로세스가있을 수 있습니다.

각 프로세스는 고유 한 현재 작업 디렉토리 (cwd)를 가질 수 있습니다 (일부 환경에서는 각 스레드에 고유 한 cwd 또는 cwd와 동등한 기능을 제공하지만이를 무시합니다).

앞의 사실은 tty에서 cwd 로의 일종의 추적을 설정합니다. tty-> 포 그라운드 프로세스 그룹-> 포 그라운드 프로세스 그룹의 프로세스-> cwds.

문제의 첫 번째 부분 (tty에서 전경 프로세스까지)은 ps 의 출력으로 해결할 수 있습니다 .

ps -o tty,pid,tpgid,pgid,state,command | awk 'BEGIN{t=ARGV[1];ARGC=1} $1==t && $3==$4 {print $2}' ttyp6

(여기서 "ttyp6"은 관심있는 tty의 이름입니다)

프로세스 (PID)에서 cwd 로의 맵핑은 lsof를 사용 하여 만들 수 있습니다 .

lsof -F 0n -a -p 2515,2516 -d cwd

(여기서“2515,2516”은 쉼표로 구분 된 관심있는 프로세스 목록입니다)

그러나 Tiger에서는 특정 터미널 창의 tty 장치 이름을 얻는 직접적인 방법이 없습니다 . Tiger에서 tty 이름을 얻는 끔찍한 추악한 방법이 있습니다. 아마도 Leopard 또는 Snow Leopard가 더 잘할 수 있습니다.

다음과 같이 AppleScript에 모두 정리했습니다.

on run
    (* Find the tty. *)
    -- This is ugly. But is seems to work on Tiger. Maybe newer releases can do better.
    tell application "Terminal"
        set w to window 1
        tell w
            set origName to name
            set title displays device name to not title displays device name
            set newName to name
            set title displays device name to not title displays device name
        end tell
    end tell
    set tty to extractTTY(origName, newName)
    if tty is "" then
        display dialog "Could not find the tty for of the current Terminal window." buttons "Cancel" cancel button "Cancel" default button "Cancel"
    end if

    (* Find the PIDs of the processes in the foreground process group on that tty. *)
    set pids to paragraphs of (do shell script "
ps -o pid,tty,tpgid,pgid,state,command |
awk '
    BEGIN   {t=ARGV[1];ARGC=1}
    $2==t && $3==$4 {print $1}
' " & quoted form of tty)
    if pids is {} or pids is {""} then
        display dialog "Could not find the processes for " & tty & "." buttons "Cancel" cancel button "Cancel" default button "Cancel"
    end if

    (* Find the unique cwds of those processes. *)
    set text item delimiters to {","}
    set lsof to do shell script "lsof -F 0n -a -d cwd -p " & quoted form of (pids as Unicode text) without altering line endings
    set text item delimiters to {(ASCII character 0) & (ASCII character 10)}
    set cwds to {}
    repeat with lsofItem in text items of lsof
        if lsofItem starts with "n" then
            set cwd to text 2 through end of lsofItem
            if cwds does not contain cwd then ¬
                set end of cwds to cwd
        end if
    end repeat
    if cwds is {} then
        display dialog "No cwds found!?" buttons "Cancel" cancel button "Cancel" default button "Cancel"
    end if
    if length of cwds is greater than 1 then
        set cwds to choose from list cwds with title "Multiple Distinct CWDs" with prompt "Choose the directory to use:" without multiple selections allowed and empty selection allowed
        if cwds is false then error number -128 -- cancel
    end if

    (* Open a new Terminal. *)
    tell application "Terminal" to do script "cd " & quoted form of item 1 of cwds
end run

to extractTTY(a, b)
    set str to textLeftAfterRemovingMatchingHeadAndTail(a, b)
    set offs to offset of "tty" in str
    if offs > 0 then
        return text offs through (offs + 4) of str
    end if
    return ""
end extractTTY
to textLeftAfterRemovingMatchingHeadAndTail(big, little)
    set text item delimiters to space
    if class of big is not list then set big to text items of big
    if class of little is not list then set little to text items of little
    set {maxLen, minLen} to {length of big, length of little}
    if maxLen < minLen then ¬
        set {big, little, maxLen, minLen} to {little, big, minLen, maxLen}

    set start to missing value
    repeat with i from 1 to minLen
        if item i of big is not equal to item i of little then
            set start to i
            exit repeat
        end if
    end repeat
    if start is missing value then
        if maxLen is equal to minLen then
            return ""
        else
            return items (minLen + 1) through end of big as Unicode text
        end if
    end if

    set finish to missing value
    repeat with i from -1 to -minLen by -1
        if item i of big is not equal to item i of little then
            set finish to i
            exit repeat
        end if
    end repeat
    if finish is missing value then set finish to -(minLen + 1)

    return items start through finish of big as Unicode text
end textLeftAfterRemovingMatchingHeadAndTail

스크립트 편집기 ( Snow Leopard의 AppleScript 편집기) 로 저장하고 실행기 (예 : FastScripts )를 사용하여 키에 지정하거나 AppleScript 메뉴 ( / Applications / AppleScript / AppleScript Utility.app 를 통해 활성화)에서 실행하십시오 .


1

나는 한 스크립트 게시 사용 크리스 욘센 의 위의 코드와 내 터미널 색 좌표를 주로하기 때문에, 현재 설정으로 현재 디렉토리에 새 탭을 열 수있는 또 다른 스크립트를. 고마워 크리스, 그 스크립트에 대해, 나는 이것을 몇 달 동안 사용해 왔으며 시간을 절약 할 수 있습니다.

(*이 스크립트는 같은 설정으로 현재 탭의 디렉토리에 새로운 Terminal.app 탭을 열고 여기에 설명 된대로가 아직 없으면, 보조 장치에 대한 액세스를 활성화해야합니다 :. HTTP : // WWW .macosxautomation.com / applescript / uiscripting / index.html

두 스크립트의 작업이 거의 다 이루어졌습니다. 감사합니다.

Chris Johnsen의 스크립트는 현재 디렉토리에서 새 탭을 엽니 다. OS X Terminal.app : 현재 탭과 동일한 디렉토리에서 새 탭을 시작하는 방법?

Jacob Rus의 "menu_click"을 사용하면 터미널의 API와는 달리 동일한 설정으로 탭을 만들 수 있습니다. http://hints.macworld.com/article.php?story=20060921045743404

터미널 프로파일의 이름을 변경하면 AppleScript API는 응용 프로그램을 다시 시작할 때까지 이전 이름을 반환하므로 스크립트는 그때까지 이름이 바뀐 설정에서 작동하지 않습니다. 어. 또한 메뉴 명령을 실행하기 위해 터미널을 활성화해야 할 경우 모든 터미널 창을 앞으로 가져옵니다.

*)

-- from http://hints.macworld.com/article.php?story=20060921045743404
-- `menu_click`, by Jacob Rus, September 2006
-- 
-- Accepts a list of form: `{"Finder", "View", "Arrange By", "Date"}`
-- Execute the specified menu item.  In this case, assuming the Finder 
-- is the active application, arranging the frontmost folder by date.

on menu_click(mList)
    local appName, topMenu, r

    -- Validate our input
    if mList's length < 3 then error "Menu list is not long enough"

    -- Set these variables for clarity and brevity later on
    set {appName, topMenu} to (items 1 through 2 of mList)
    set r to (items 3 through (mList's length) of mList)

    -- This overly-long line calls the menu_recurse function with
    -- two arguments: r, and a reference to the top-level menu
    tell application "System Events" to my menu_click_recurse(r, ((process appName)'s ¬
        (menu bar 1)'s (menu bar item topMenu)'s (menu topMenu)))
end menu_click

on menu_click_recurse(mList, parentObject)
    local f, r

    -- `f` = first item, `r` = rest of items
    set f to item 1 of mList
    if mList's length > 1 then set r to (items 2 through (mList's length) of mList)

    -- either actually click the menu item, or recurse again
    tell application "System Events"
        if mList's length is 1 then
            click parentObject's menu item f
        else
            my menu_click_recurse(r, (parentObject's (menu item f)'s (menu f)))
        end if
    end tell
end menu_click_recurse



-- with the noted slight modification, from https://superuser.com/questions/61149/os-x-terminal-app-how-to-start-a-new-tab-in-the-same-directory-as-the-current-ta/61264#61264

on run
    (* Find the tty. *)
    -- This is ugly. But is seems to work on Tiger. Maybe newer releases can do better.
    tell application "Terminal"
        set w to the front window
        tell w
            set origName to name
            set title displays device name to not title displays device name
            set newName to name
            set title displays device name to not title displays device name
        end tell
    end tell
    set tty to extractTTY(origName, newName)
    if tty is "" then
        display dialog "Could not find the tty for of the current Terminal window." buttons "Cancel" cancel button "Cancel" default button "Cancel"
    end if

    (* Find the PIDs of the processes in the foreground process group on that tty. *)
    set pids to paragraphs of (do shell script "
ps -o pid,tty,tpgid,pgid,state,command |
awk '
    BEGIN   {t=ARGV[1];ARGC=1}
    $2==t && $3==$4 {print $1}
' " & quoted form of tty)
    if pids is {} or pids is {""} then
        display dialog "Could not find the processes for " & tty & "." buttons "Cancel" cancel button "Cancel" default button "Cancel"
    end if

    (* Find the unique cwds of those processes. *)
    set text item delimiters to {","}
    set lsof to do shell script "lsof -F 0n -a -d cwd -p " & quoted form of (pids as Unicode text) without altering line endings
    set text item delimiters to {(ASCII character 0) & (ASCII character 10)}
    set cwds to {}
    repeat with lsofItem in text items of lsof
        if lsofItem starts with "n" then
            set cwd to text 2 through end of lsofItem
            if cwds does not contain cwd then ¬
                set end of cwds to cwd
        end if
    end repeat
    if cwds is {} then
        display dialog "No cwds found!?" buttons "Cancel" cancel button "Cancel" default button "Cancel"
    end if
    if length of cwds is greater than 1 then
        set cwds to choose from list cwds with title "Multiple Distinct CWDs" with prompt "Choose the directory to use:" without multiple selections allowed and empty selection allowed
        if cwds is false then error number -128 -- cancel
    end if

    (* Open a new Terminal. *)

    -- Here is where I substituted the menu_click call to use the current settings

    tell application "Terminal"
        activate
        tell window 1
            set settings to name of current settings in selected tab
        end tell
    end tell
    menu_click({"Terminal", "Shell", "New Tab", settings})

    tell application "Terminal" to do script "cd " & quoted form of item 1 of cwds in selected tab of window 1
end run

to extractTTY(a, b)
    set str to textLeftAfterRemovingMatchingHeadAndTail(a, b)
    set offs to offset of "tty" in str
    if offs > 0 then
        return text offs through (offs + 6) of str
    end if
    return ""
end extractTTY
to textLeftAfterRemovingMatchingHeadAndTail(big, little)
    set text item delimiters to space
    if class of big is not list then set big to text items of big
    if class of little is not list then set little to text items of little
    set {maxLen, minLen} to {length of big, length of little}
    if maxLen < minLen then ¬
        set {big, little, maxLen, minLen} to {little, big, minLen, maxLen}

    set start to missing value
    repeat with i from 1 to minLen
        if item i of big is not equal to item i of little then
            set start to i
            exit repeat
        end if
    end repeat
    if start is missing value then
        if maxLen is equal to minLen then
            return ""
        else
            return items (minLen + 1) through end of big as Unicode text
        end if
    end if

    set finish to missing value
    repeat with i from -1 to -minLen by -1
        if item i of big is not equal to item i of little then
            set finish to i
            exit repeat
        end if
    end repeat
    if finish is missing value then set finish to -(minLen + 1)

    return items start through finish of big as Unicode text
end textLeftAfterRemovingMatchingHeadAndTail


0

이 별칭 / 쉘 스크립트를 사용하여 수행합니다.

# modified from http://www.nanoant.com/programming/opening-specified-path-in-terminals-new-tab
alias twd=new_terminal_working_directory
function new_terminal_working_directory() {
osascript <<END 
        tell application "Terminal"
            tell application "System Events" to tell process "Terminal" to keystroke "t" using command down
        do script "cd $(pwd)" in first window
    end tell
END
}

1
cwd에 특정 문자 (쉘 메타 문자 및 제어 토큰 (예 : 공백이있는 디렉토리))가 있으면 문제가 발생하는 것처럼 보입니다.
Chris Johnsen

당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.