이전 / 다음 형제 디렉토리로 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.