Làm thế nào tôi có thể cd vào thư mục anh chị em trước / tiếp theo?


10

Tôi thường có một bố cục thư mục dự án như thế này

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

Tôi thường sẽ làm việc trong một trong các componentthư mục, vì đó là nơi chứa các tệp. Sau đó, khi tôi trở lại trình bao, tôi thường chỉ cần chuyển đến một thư mục anh chị em, đặc biệt là khi tôi cần thực hiện một vài thay đổi không có kịch bản cho mọi thành phần. Trong những trường hợp đó, tôi thậm chí sẽ không quan tâm thư mục anh chị em trước đó là gì mà tôi sẽ làm việc hoặc thư mục anh chị em tiếp theo.

Tôi có thể định nghĩa một lệnh prevhoặc nextđơn giản là cdtôi sẽ vào thư mục trước hoặc thư mục tiếp theo (theo bảng chữ cái hoặc bất cứ điều gì)? Bởi vì gõ cd ../com<TAB><Arrow keys>tất cả thời gian là một chút cũ.

Câu trả lời:


8

Không sử dụng giải pháp dòng lệnh từ câu trả lời khác : không an toàn VÀ không hiệu quả.² Thay vào đó, nếu bạn đang sử dụng bash, chỉ cần sử dụng các chức năng sau. Để làm cho họ bền bỉ, đặt chúng vào của bạn .bashrc. Lưu ý rằng tôi sử dụng thứ tự toàn cầu vì nó tích hợp và dễ dàng. Thông thường thứ tự toàn cầu bảng chữ cái ở hầu hết các địa phương mặc dù. Bạn sẽ nhận được thông báo lỗi nếu không có thư mục tiếp theo hoặc trước đó. Cụ thể, bạn sẽ thấy lỗi nếu bạn cố gắng nexthoặc prevtrong khi trong thư mục gốc , /.

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

Nó không xử lý tất cả các tên thư mục có thể. Phân tích cú pháp lsđầu ra không bao giờ an toàn .

² cdcó lẽ không cần phải hiệu quả khủng khiếp, nhưng 6 quy trình thì hơi quá.


1
Tôi thực sự sử dụng zsh, nhưng nếu bạn thay đổi bài kiểm tra đầu tiên trong vòng lặp for của vòng tiếp theo thành [[ -n $foundcwd ]]câu trả lời thì câu trả lời của bạn cũng hoạt động tốt như bash và zsh. Rất đẹp, và cảm ơn bạn đã viết lên.
Esteis

4

Hàm sau cho phép thay đổi thành thư mục anh chị em (hàm 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
}

Một ví dụ về sử dụng:

$ 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

Rất đẹp. Tôi đang giữ câu trả lời của jw013 là câu trả lời được chấp nhận, bởi vì câu hỏi và trường hợp sử dụng của tôi là 'Tôi muốn chuyển sang anh chị em tiếp theo và tôi không quan tâm nó được gọi là gì'; nhưng điều này cũng hữu ích và tiện lợi, vì vậy hãy có một upvote.
Esteis

2

Tôi tìm thấy một mẹo trên tại Commandlinefu.com . Tôi đang đăng lại nó ở đây để làm cho nó dễ tìm thấy hơn, với một lời giải thích và một nextlệnh được thêm vào trong khi tôi đang ở đó.

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)"'

Phép thuật nằm trong khối `$ (...). Nó nối một vài lệnh vào nhau như sau:

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
Lệnh bạn tìm thấy có một số vấn đề. Tôi đã chỉnh sửa nó để sửa những cái nghiêm trọng nhất: nó đã coi tên thư mục là một mẫu grep và cho phép nó khớp với một chuỗi con; và nó có tên thư mục trải qua quá trình mở rộng shell (chia tách từ và tạo khối) hai lần (luôn luôn sử dụng dấu ngoặc kép xung quanh các thay thế biến và lệnh : "$foo", "$(foo)"). Ngoài ra, phân tích cú pháp đầu ra lslà không đáng tin cậy , nó có thể thất bại với tên tệp chứa các ký tự không thể in được.
Gilles 'SO- ngừng trở nên xấu xa'
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.