이전 / 다음 형제 디렉토리로 CD를 넣으려면 어떻게해야합니까?


10

나는 종종 이와 같은 프로젝트 디렉토리 레이아웃을 가지고 있습니다

project
`-- component-a
|   `-- files...
`-- component-b
|   `-- files...
`-- component-c
    `-- files...

component파일이있는 곳이기 때문에 일반적으로 디렉토리 중 하나에서 작업 합니다. 그런 다음 쉘로 돌아올 때, 특히 모든 구성 요소를 스크립팅 할 수없는 몇 가지 사항을 변경해야 할 때 종종 형제 디렉토리로 이동해야합니다. 이 경우 이전 형제 디렉토리가 무엇인지 또는 다음 형제 디렉토리가 무엇인지 상관하지 않습니다.

명령을 정의 할 수 있습니까? prev아니면 next단순히 cd이전 디렉토리 나 다음 디렉토리 (알파벳 등)로 나에게 보내 줍니까? cd ../com<TAB><Arrow keys>항상 타이핑 하는 것이 조금 오래 되었기 때문입니다.

답변:


8

다른 답변 의 commandlinefu 솔루션을 사용하지 마십시오. 안전하지 않으며 ¹ 비효율적입니다 .² 대신을 bash사용하는 경우 다음 기능을 사용하십시오. 그들을 영구적으로 만들려면에 넣으십시오 .bashrc. 글로브 순서는 내장되어 있고 쉬우므로 사용합니다. 대부분의 로케일에서는 일반적으로 글로브 순서 알파벳순입니다. 다음 또는 이전 디렉토리가 없으면 오류 메시지가 표시됩니다. 특히 루트 디렉토리에서 next또는 시도하는 prev동안 오류가 발생합니다 /.

## bash and zsh only!
# functions to cd to the next or previous sibling directory, in glob order

prev () {
    # default to current directory if no previous
    local prevdir="./"
    local cwd=${PWD##*/}
    if [[ -z $cwd ]]; then
        # $PWD must be /
        echo 'No previous directory.' >&2
        return 1
    fi
    for x in ../*/; do
        if [[ ${x#../} == ${cwd}/ ]]; then
            # found cwd
            if [[ $prevdir == ./ ]]; then
                echo 'No previous directory.' >&2
                return 1
            fi
            cd "$prevdir"
            return
        fi
        if [[ -d $x ]]; then
            prevdir=$x
        fi
    done
    # Should never get here.
    echo 'Directory not changed.' >&2
    return 1
}

next () {
    local foundcwd=
    local cwd=${PWD##*/}
    if [[ -z $cwd ]]; then
        # $PWD must be /
        echo 'No next directory.' >&2
        return 1
    fi
    for x in ../*/; do
        if [[ -n $foundcwd ]]; then
            if [[ -d $x ]]; then
                cd "$x"
                return
            fi
        elif [[ ${x#../} == ${cwd}/ ]]; then
            foundcwd=1
        fi
    done
    echo 'No next directory.' >&2
    return 1
}

¹ 가능한 모든 디렉토리 이름을 처리하지는 않습니다. 파싱 ls출력은 결코 안전하지 않습니다 .

²는 cd아마도 매우 효율적일 필요는 없지만 6 개의 프로세스는 약간 과도합니다.


1
실제로 zsh를 사용하지만 다음 함수의 for-loop에서 첫 번째 테스트를 변경하면 [[ -n $foundcwd ]]bash와 zsh에서 똑같이 잘 작동합니다. 매우 좋으며 이것을 작성해 주셔서 감사합니다.
Esteis 2016 년

4

다음 기능은 형제 디렉토리로 변경하도록 허용합니다 (bash 기능).

function sib() {
    ## sib  search sibling directories 
    ##   prompt for choice (when two or more directories are found, current dir is removed from choices) 
    ##   change to directory after selection 
    local substr=$1
    local curdir=$(pwd)
    local choices=$(find .. -maxdepth 1 -type d -name "*${substr}*" | grep -vE '^..$' | sed -e 's:../::' | grep -vE "^${curdir##*/}$" | sort)
    if [ -z "$choices" ]; then
        echo "Sibling directory not found!"
        return
    fi
    local count=$(echo "$choices" | wc -l)
    if [[ $count -eq 1 ]]; then
        cd ../$choices
        return 
    fi
    select dir in $choices; do
        if [ -n "$dir" ]; then
            cd ../$dir
        fi
        break
    done
}

사용 예 :

$ tree
  .
  ├── component-aaa-01
  ├── component-aaa-02
  ├── component-bbb-01
  ├── component-bbb-02
  ├── component-ccc-01
  ├── component-ccc-02
  └── component-ccc-03
  7 directories, 0 files
  $ cd component-aaa-01/
  $ sib bbb-01
  $ pwd
  component-bbb-01
  $ sib bbb
  $ pwd
  component-bbb-02
  $ sib ccc
  1) component-ccc-01
  2) component-ccc-02
  3) component-ccc-03
  #? 3
  $ pwd
  component-ccc-03
  $ sib 01
  1) component-aaa-01
  2) component-bbb-01
  3) component-ccc-01
  #? 2
  $ pwd
  component-bbb-01

아주 좋아요 나는 jw013의 대답을 받아 들인 대답으로 유지하고 있습니다. 제 질문과 유스 케이스는 '다음 형제로 옮기고 싶습니다. 그러나 이것은 또한 유용하고 깔끔하며 공감대도 있습니다.
Esteis

2

commandlinefu.com 에서 팁을 찾았습니다 . 나는 그것을 찾을 수 있도록 설명과 next명령을 추가 하여 더 쉽게 찾을 수 있도록 여기에 다시 게시하고 있습니다 .

alias prev='cd ../"$(ls -F .. | grep '/' | grep -B1 -xF "${PWD##*/}/" | head -n 1)"'
alias next='cd ../"$(ls -F .. | grep '/' | grep -A1 -xF "${PWD##*/}/" | tail -n 1)"'

마법은`$ (...) 블록에 있습니다. 다음과 같이 몇 가지 명령을 서로 연결합니다.

ls -F .. |   # list items in parent dir; `-F` requests filetype indicators
grep '/' |   # select the directories (written as  `mydir/`)
grep -B1 -xF "${PWD##*/}/" |   # search for the name of the current directory in the output;
                               # print it and the line preceding it
head -n 1    # the first of those two lines contains the name of the previous sibling

2
찾은 명령에는 여러 가지 문제가 있습니다. 가장 까다로운 것을 수정하기 위해 편집했습니다 : 디렉토리 이름을 grep 패턴으로 취급하고 하위 문자열과 일치하도록 허용했습니다. 그리고 디렉토리 이름에 쉘 확장 (단어 분할 및 globbing)이 두 번 수행됩니다 (변수 및 명령 대체 : "$foo", "$(foo)") 에는 항상 큰 따옴표를 사용하십시오 ). 또한 출력을 구문 분석하는 ls것은 신뢰할 수 없으며 인쇄 할 수없는 문자가 포함 된 파일 이름으로 인해 실패 할 수 있습니다.
Gilles 'SO- 악한 중지'
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.