Bash CD cho đến khi trong thư mục nhất định


16

Tôi làm rất nhiều việc ở Magento và rất nhiều người tôi làm việc cùng, và thật khó chịu khi phải gõ:

cd ../../../../../../

Để chỉ tìm thấy bạn vẫn còn một vài thư mục từ thư mục 'httpdocs' gốc của bạn, vì vậy tôi đang cố gắng tạo một tập lệnh tuân theo mã giả này:

while lowest level directory != httpdocs
    cd ../
end while;

Có vẻ khá đơn giản, tôi giả sử rằng tôi sẽ phải thực hiện một số hình thức grep khi kiểm tra xem phần cuối của thư mục làm việc hiện tại có phải là httpdocs hay không, nếu không cứ tiếp tục tăng lên cho đến khi nó thành sự thật.

Tôi đã xem xét việc học bash cho việc này, mặc dù có vẻ như phải có một cái gì đó tương tự, và cú pháp đánh đố tôi không có hồi kết.

Câu trả lời:


8

Đây phải là một hàm shell , không phải là script, bởi vì script thực thi trong shell mới (và do đó không thể thay đổi thư mục của shell gốc).

function cdroot()
{
  while [[ $PWD != '/' && ${PWD##*/} != 'httpdocs' ]]; do cd ..; done
}

Tất nhiên bạn có thể đặt tên cho chức năng bất cứ điều gì bạn thích.

Một số giải thích: Thử nghiệm đầu tiên ( $PWD != '/') là không an toàn trong trường hợp bạn thực hiện cdrootkhi bạn không ở trong thư mục httpdocs. Nó sẽ dừng lại khi bạn đến gốc.

Bài kiểm tra thứ hai ( ${PWD##*/} != 'httpdocs') phức tạp hơn một chút. $PWDlà một biến chứa đường dẫn của thư mục hiện tại. ${PWD##*/}cắt mọi thứ lên đến và bao gồm cả dấu gạch chéo cuối cùng.


Nhược điểm của việc lặp đi lặp lại này là bạn mất khả năng chỉ làm một việc cd -sau đó để quay lại nơi bạn đang ở.
Ezequiel Muns

27

Tôi có một hàm được gọi uptotrong .bashrc của tôi, cho phép bạn đi đến bất kỳ thư mục nào trên đường dẫn hiện tại theo tên:

upto ()
{
    if [ -z "$1" ]; then
        return
    fi
    local upto=$1
    cd "${PWD/\/$upto\/*//$upto}"
}

Tôi cũng đã hoàn thành chức năng này, để nó cung cấp cho tôi tên thư mục hợp lệ và hoàn thành khi tôi nhấn tab:

_upto()
{
    local cur=${COMP_WORDS[COMP_CWORD]}
    local d=${PWD//\//\ }
    COMPREPLY=( $( compgen -W "$d" -- "$cur" ) )
}
complete -F _upto upto

Ngoài ra, tôi có một chức năng khác jdcho phép tôi chuyển đến bất kỳ thư mục nào bên dưới thư mục hiện tại:

jd(){
    if [ -z "$1" ]; then
        echo "Usage: jd [directory]";
        return 1
    else
        cd **"/$1"
    fi
}

Thí dụ:

[/www/public_html/animals/hippopotamus/habitat/swamps/images] $ upto h[TAB][TAB]
habitat       hippopotamus
[/www/public_html/animals/hippopotamus/habitat/swamps/images] $ upto hippopotamus
[/www/public_html/animals/hippopotamus] $ jd images
[/www/public_html/animals/hippopotamus/habitat/swamps/images] $ 

Bạn cũng có thể thêm một bí danh cho upto httpdocs.
cjm

@drogbane: jddường như không hoạt động trong mọi trường hợp, bạn có phiền giải thích cách nó hoạt động không?
Cesar

@Cesar nó sử dụng globalstar ( **). Để kích hoạt tính năng này trong sử dụng bash shell của bạn shopt -s globstar.
dogbane

2
Điều này được thực hiện một cách tuyệt vời, tôi ước tôi có thể nâng cấp hai lần.
droope

1
Tôi đã bao gồm một phát hiện và kích hoạt shopt động trong jdchức năng, xem gist.github.com/Rob--W/5888648 . Tôi chỉ thử nghiệm nó với Bash 4.2.45, vì vậy YMMV.
Rob W

5

Hàm bash đơn giản nhất mà bạn có thể đưa vào .bashrcmà bạn có thể nghĩ đến (đơn giản vì nó không sử dụng các vòng lặp hoặc các quy trình bên ngoài) là:

cdup() {
    cd "${PWD/\/httpdocs\/*//httpdocs}"
}

Này sử dụng mẫu thay thế mở rộng tham số để thay thế tất cả mọi thứ sau /httpdocs/trong $PWDvới `/ httpdocs'. Nó trông rất lộn xộn bởi vì chúng ta phải thoát các dấu gạch chéo về phía trước trong đường dẫn để phân biệt chúng với các dấu gạch chéo về phía trước trong cú pháp mở rộng bash. Ngoài ra, không thoát các dấu gạch chéo về phía trước trong chuỗi thay thế, vì vậy nó cũng không nhất quán.

Nếu không có /httpdocs/trong đường dẫn hiện tại thì sẽ không có sự thay thế nào được thực hiện và nó sẽ chỉ thay đổi thành thư mục hiện tại.

Ví dụ, sự thay thế sẽ thay thế /a/b/c/httpdocs/e/f/gbằng /a/b/c/httpdocscdvào thư mục đó.

Hàm cần phải ở trong môi trường shell hiện tại của bạn (có thể là hàm hoặc bí danh) vì một tiến trình con không thể thay đổi thư mục hiện tại của cha mẹ của nó. Đây là lý do tại sao tôi nói để đặt nó trong của bạn .bashrcvà không phải trong một kịch bản shell.


Ngẫu nhiên, điều đáng nói là điều này sẽ đưa bạn lên cao trong hệ thống phân cấp nhất có thể (dù sao đây có lẽ là trường hợp sử dụng hữu ích nhất).
Ibrahim

3

Bạn cũng có thể đặt một cái gì đó như thế này trong hồ sơ của bạn:

alias cdh='cd $(echo $PWD | sed -e "s/\(.*\/httpdocs\)\/.*/\1/")'

Chỉ cần gõ cdhsẽ đưa bạn đến httpdocsthư mục trên cùng trong đường dẫn hiện tại của bạn.


2

Nó không hoàn toàn giải quyết vấn đề của bạn, nhưng nó sẽ tiết kiệm khi làm cd ../../../../../../ một chút. Tôi đã mượn cái này từ bài đăng của người dùng chưa biết ở đây .


lên N

nhảy N thư mục lên trong cây thư mục

Thay vì gõ

cd ../../../..

bạn chỉ cần gõ

up 4

và một

cd -    

sẽ mang bạn trở lại

Đặt hàm vào .bashrc của bạn để sử dụng nó.

# (c) 2007 stefan w. GPLv3          
function up {
ups=""
for i in $(seq 1 $1)
do
        ups=$ups"../"
done
cd $ups
}
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.