Chúng ta có nhiều lịch sử cho cd?


Câu trả lời:


31

Lệnh bạn đang tìm là pushdpopd.

Bạn có thể xem một ví dụ làm việc thực tế của pushdpopdtừ đây .

mkdir /tmp/dir1
mkdir /tmp/dir2
mkdir /tmp/dir3
mkdir /tmp/dir4

cd /tmp/dir1
pushd .

cd /tmp/dir2
pushd .

cd /tmp/dir3
pushd .

cd /tmp/dir4
pushd .

dirs
/tmp/dir4 /tmp/dir4 /tmp/dir3 /tmp/dir2 /tmp/dir1

1
Cũng có $OLDPWDtrường hợp bạn muốn lật qua lại giữa hai thư mục bằng cùng một lệnh, nhưng tôi không chắc chắn mức độ cụ thể của vỏ và phân phối / hạt nhân cụ thể này.
điện tử

4
@ivy_lynx OLDPWDtồn tại trong tất cả các vỏ POSIX, nhưng câu hỏi này vô dụng đối với câu hỏi này làm thế nào để vượt qua điều đó (câu hỏi đã đề cập đến cd -đó là lối tắt cho cd "$OLDPWD").
Gilles 'SO- ngừng trở nên xấu xa'

2
Có một lý do bạn sử dụng cd /tmp/dir1; pushd . thay vì chỉ pushd /tmp/dir1?
GnP

@gnp, không có lý do cụ thể. Nó chỉ được lấy từ liên kết mà tôi đã đề cập trong câu trả lời. pushd /tmp/dir1nên làm việc tốt
Ramesh

1
Ok, chỉ cần chọn sự tò mò của tôi. Tôi muốn đề nghị bạn cải thiện câu trả lời của mình bằng một ví dụ thực tế bằng cách sử dụng pushdvà duyệt popdqua cây thư mục qua lại. Câu trả lời của bạn đã là câu trả lời đúng.
GnP

53

Bạn đã không chỉ định shell nào bạn đang sử dụng, vì vậy hãy coi đây là lý do để quảng cáo zsh.

Có, chúng tôi có nhiều lịch sử hơn cd, cụ thể là cd -2, cd -4v.v ... Rất tiện lợi cd -TAB, đặc biệt là với hệ thống hoàn thành và màu sắc được bật:

Đây là những gì tôi có trong .zshrc:

setopt AUTO_PUSHD                  # pushes the old directory onto the stack
setopt PUSHD_MINUS                 # exchange the meanings of '+' and '-'
setopt CDABLE_VARS                 # expand the expression (allows 'cd -2/tmp')
autoload -U compinit && compinit   # load + start completion
zstyle ':completion:*:directory-stack' list-colors '=(#b) #([0-9]#)*( *)==95=38;5;12'

Và kết quả:

nhập mô tả hình ảnh ở đây


4
bash bash bash bash
Tim

7
OK, tôi sẽ không xóa câu trả lời này, có thể sẽ hữu ích cho những người khác.
jimmij

23
Trừ khi câu hỏi đặc biệt hỏi về bash, đây là một câu trả lời hợp lệ. Đừng loại bỏ nó.
liori

Điều gì xảy ra nếu OP chỉnh sửa câu hỏi của anh ấy để chỉ bao gồm bash, câu trả lời này có còn hiệu lực không?
Ooker

3
Nó có thể chịu đề cập rằng ngoài setopt AUTO_PUSHD, không có thiết lập nào ở trên được yêu cầu để có được một ngăn xếp thư mục toàn diện với sự hoàn thành trong kho zsh. PUSHD_MINUSđảo ngược ý nghĩa cd +cd -(một vấn đề của hương vị), CDABLE_VARSkhông liên quan đến ngăn xếp thư mục, và zstylelời mời được đưa ra ở đây chỉ đơn giản là thêm màu vào đầu ra của việc hoàn thành ngăn xếp thư mục. Tuy nhiên, người ta phải khởi tạo hệ thống con hoàn thành với autoload -U compinit && compinit.
wjv

13

Để trả lời câu hỏi của bạn về "lịch sử nhiều hơn". Không có cd -tính năng nào trong Bash chỉ hỗ trợ một thư mục duy nhất mà bạn có thể "lật" lại. Như @Ramesh nói trong câu trả lời của mình. Nếu bạn muốn có một lịch sử lâu hơn của các thư mục, bạn có thể sử dụng pushdpopdlưu một thư mục hoặc quay lại thư mục trước đó.

Bạn cũng có thể xem danh sách những gì hiện có trong ngăn xếp với dirslệnh.

Một lời giải thích chi tiết có thể được tìm thấy từ câu trả lời này có tiêu đề: Làm thế nào để tôi sử dụng các lệnh Pushd và popd? .


Tôi đã bao gồm một tài liệu tham khảo từ câu trả lời của bạn. Hy vọng bạn không phiền. :)
Ramesh

@Ramesh - Không đi trước.
slm

8

Bạn có thể cài đặt và sử dụng tiện ích dirhistory của tôi cho bash.

Về cơ bản, đó là một daemon thu thập các thay đổi thư mục từ tất cả các shell của bạn và chương trình Cdk hiển thị lịch sử và cho phép bạn chọn bất kỳ thư mục nào để chuyển sang (vì vậy bạn không bị giới hạn trong một ngăn xếp).


7

Bạn có nhiều lịch sử như bạn muốn:

cd() {
[ "$((${DIRSTACKMAX##*[!0-9]*}0/10))" -gt 0 ] &&
        set -- "$@" "$DIRSTACK"               &&
        DIRSTACK='pwd -P >&3; command cd'     ||
        { command cd "$@"; return; }
_q()    while   case "$1" in (*\'*) :   ;;      (*)
                ! DIRSTACK="$DIRSTACK '$2$1'"   ;;esac
        do      set -- "${1#*\'}" "$2${1%%\'*}'\''"
        done
while   [ "$#" -gt 1 ]
do      case    ${1:---} in (-|[!-]*|-*[!0-9]*) : ;;
        (*)     eval "  set $((${1#-}+1))"' "${'"$#}\""
                eval '  set -- "$2"'" $2"'
                        set -- "${'"$1"'}" "$1"'
        ;;esac; _q "$1"; shift
done
eval "  DIRSTACK=; $DIRSTACK    &&"'
        _q "$OLDPWD"            &&
        DIRSTACK=$DIRSTACK\ $1
        set "$?" "${DIRSTACK:=$1}"'" $1
"       3>/dev/null
[ "$(($#-1))" -gt "$DIRSTACKMAX" ] &&
        DIRSTACK="${DIRSTACK% \'/*}"
unset -f _q; return "$1"
}

Đó là một hàm shell sẽ cho phép mọi shell tương thích POSIX cung cấp lịch sử zshkiểu cd. Nó thực hiện tất cả công việc của nó mà không cần gọi một subshell duy nhất, và tôi tin rằng dòng chảy của nó là âm thanh khá - nó dường như xử lý tất cả các trường hợp chính xác trong thử nghiệm vừa phải.

Hàm cố gắng chơi độc đáo với môi trường của nó như có thể trong khi vẫn dựa vào cú pháp hoàn toàn di động - nó chỉ đưa ra một giả định và đó là $DIRSTACKbiến môi trường là thuộc tính của nó.

Nó hợp thức hóa tất cả các đường dẫn mà nó lưu trữ $DIRSTACKvà tuần tự hóa tất cả chúng trên các dấu ngoặc đơn - mặc dù nó đảm bảo mỗi đường dẫn được trích dẫn và tuần tự hóa một cách an toàn trước khi thêm nó vào giá trị của biến và không nên có bất kỳ vấn đề nào với bất kỳ ký tự đặc biệt nào. . Nếu $DIRSTACKMAXbiến môi trường được đặt, nó sẽ sử dụng nó làm giới hạn trên cho số lượng đường dẫn mà nó giữ lại trong lịch sử, nếu không thì giới hạn là một.

Nếu bạn tải chức năng, bạn vẫn cdbình thường nhưng cũng có thể thực hiện việc cd -[num]lấy lại thông qua lịch sử thư mục thay đổi của bạn.

Cơ chế chính của hàm là cdchính nó - và các ${OLD,}PWDbiến môi trường. POSIX chỉ định cdthay đổi những thay đổi này cho mỗi lần di chuyển đường dẫn - và do đó, điều này chỉ sử dụng các biến dựng sẵn của shell và lưu các giá trị bao lâu tùy thích.


@datUser - Tôi biết ai đó đã có một dat. bạn khá hoan nghênh
mikeerv

4

Các acd_func.sh kịch bản thực hiện chính xác những gì bạn mô tả. Về cơ bản, nó làm quá tải cdchức năng và cho phép bạn nhập cd --để có danh sách các thư mục đã truy cập trước đó, từ đó bạn có thể chọn theo số. Tôi thấy rất khó để sử dụng bash mà không có điều này nữa, và đó là điều đầu tiên tôi cài đặt trên một hệ thống mới.



3

Những người khác đã bao gồm một số giải pháp thú vị. Cách đây một thời gian, tôi đã tạo ra giải pháp của riêng mình cho một vấn đề liên quan có thể được sửa đổi nhanh chóng để làm "lịch sử thẳng". Về cơ bản, tôi muốn "gắn nhãn" một vài thư mục thường được sử dụng và muốn tất cả các shell mở để xem chúng và để chúng tồn tại giữa các lần khởi động lại.

#dir_labels
#functions to load and retrieve list of dir aliases

function goto_complete {
    unset dir_labels
    declare -A dir_labels
    {
    while read line; do
        ll_pre="${line%% *}"
        ll_dir="${line#* }"
        dir_labels["$ll_pre"]="$ll_dir"
    done
    } < ~/.dir_labels
    unset ll_pre
    unset ll_dir

    local cur possib
    cur="${COMP_WORDS[COMP_CWORD]}"
    possib="${!dir_labels[@]}"
    COMPREPLY=( $(compgen -W "${possib}" -- ${cur}) )
}

complete -F goto_complete goto

function goto {
    unset dir_labels
    declare -A dir_labels
    {
    while read line; do
        ll_pre="${line%% *}"
        ll_dir="${line#* }"
        dir_labels["$ll_pre"]="$ll_dir"
    done
    } < ~/.dir_labels
    unset ll_pre
    unset ll_dir

    if [ $# -gt 0 ]; then
    key="$1"
    else
    key=default
    fi
    target="${dir_labels[$key]}"
    if [ -d "$target" ]; then
    cd "$target"
    echo "goto $key: '$target'"
    else
    echo "directory '$target' does not exist"
    fi
}

function label {
    unset dir_labels
    declare -A dir_labels
    {
    while read line; do
        ll_pre="${line%% *}"
        ll_dir="${line#* }"
        dir_labels["$ll_pre"]="$ll_dir"
    done
    } < ~/.dir_labels
    unset ll_pre
    unset ll_dir

    if [ $# -gt 0 ]; then
    target="$1"
    else
    target="default"
    fi
    dir_labels["$target"]=$PWD
    for i in "${!dir_labels[@]}"; do
    echo "$i ${dir_labels[$i]}"
    done > ~/.dir_labels
}

Về cơ bản tôi chỉ muốn làm label foođể gọi thư mục hiện hành foo, và sau đó từ bất cứ shell, goto foowhould cdthẳng tới đó. Đối số trống: labelsẽ tạo một mục tiêu mặc định cho goto.

Tôi không bận tâm đến việc tự động loại bỏ các bí danh, nhưng nếu không, tôi vẫn đang sử dụng điều này ở dạng hơi sửa đổi.


2

Bạn có thể sử dụng chức năng "lịch sử cd" của tôi từ http://fex.belwue.de/fstools/bash.html

Nó ghi nhớ mọi thư mục nơi bạn đã đến và với "cdh", bạn sẽ thấy một danh sách 9 thư mục cuối cùng. Chỉ cần nhập số và bạn trở lại trong thư mục này.

Thí dụ:

framstag @ wupp: /: cdh
1: / usr / cục bộ / thùng
2: / var
3: /
4: / tmp / 135_pana / 1280
5: / tmp / 135_pana
6: / tmp / weihnachtsfeier
7: / tmp
8: / địa phương / nhà / framstag
chọn: 4
framstag @ wupp: / tmp / 135_pana / 1280:

cdh hoạt động với autocd aka "cd without cd": bạn không phải gõ cd hoặc Pushd.


2

Tôi muốn giới thiệu chức năng 'cd' mở rộng của mình cho bạn:

https://github.com/dczhu/ltcd

nhập mô tả hình ảnh ở đây

Nó cung cấp các tính năng sau để làm cho cuộc sống dễ dàng hơn:

  • Danh sách thư mục toàn cầu, hiển thị các thư mục được truy cập gần đây từ tất cả các tab / cửa sổ đầu cuối.
  • Danh sách thư mục địa phương, đó là phiên bản cục bộ hiện tại.
  • Cả hai danh sách đều hỗ trợ điều hướng nhanh bằng cách sử dụng j / k (đi xuống / lên), số và tìm kiếm từ.
  • Nhảy miễn phí toàn cầu (ví dụ: "cd dir" hoặc "cd ar" để đi đến / path / to / foo / bar / thư mục /).

Hừm, có vẻ đầy hứa hẹn. Tôi sẽ kiểm tra.
ddnomad

1

về bash , về cơ bản: thay vì sử dụng cd pushdđể thay đổi thư mục, vì vậy chúng được lưu (có nghĩa là xếp chồng)

pushd /home; pushd /var; pushd log

Để xem ngăn xếp sử dụng dirsvà để điều hướng dễ dàng hơn (để lấy số của "mục nhập ngăn xếp", hãy sử dụng:

dirs -v

Đầu ra:

me@myhost:/home$ dirs -v
 0  /home
 1  /var
 2  /tmp

Bây giờ sử dụng những con số này với cd~như:

cd ~1

Nhưng bây giờ các số này được sắp xếp lại ngay bây giờ và vị trí "0" sẽ thay đổi, vì vậy chỉ cần pushdthư mục đến vị trí trên cùng hai lần (hoặc sử dụng một hình nộm ở vị trí 0) như:

me@myhost:/home$ dirs -v
 0  /home
 1  /home
 2  /var
 3  /tmp

Bây giờ 1..3 sẽ giữ nguyên vị trí tôi đọc được ở đâu đó nhưng không biết nữa, rất tiếc vì đã không cung cấp tín dụng

(để giải phóng thư mục hiện tại khỏi ngăn xếp / xóa nó khỏi lịch sử sử dụng popd)


1

Xem chức năng cdh trong "Lập trình Shell, 4e" trên trang 312. Nó giữ lịch sử trong một mảng.

Đây là phiên bản nâng cao hơn: https://drive.google.com/open?id=0B4f-lR6inxQWQ1pPZVpUQ3FSZ2M

Nó lưu trữ lịch sử trong tệp CDHISTFILE và cho phép thay đổi thư mục gần đây nhất có chứa một chuỗi, ví dụ:

cd -src

Nó tự cài đặt qua lệnh cd hiện có bằng cách thực hiện alias cd=_cd


1

Chỉ muốn thêm dấu fzf như một giải pháp có thể.

Sau khi cài đặt, nó cung cấp cho bạn dấu lệnh và nhảy để thêm và tìm kiếm các thư mục được đánh dấu (vâng, nó không chính xác là lịch sử đầy đủ, chỉ có những cái bạn tự đánh dấu).

Vấn đề tôi gặp phải với Pushd / popd đó là hành vi cụ thể của phiên, tức là tôi muốn có cùng ngăn xếp trên phiên bash khác nhau hoặc do đó có thể xảy ra đối với các dấu fzf.


0

Tôi đã thử câu trả lời mà @mikeerv đưa ra, nhưng nó không hiệu quả lắm đối với tôi. Tôi không thể tìm ra cách khắc phục nó, vì vậy tôi chỉ tự viết:

cd() {
    # Set the current directory to the 0th history item
    cd_history[0]=$PWD
    if [[ $1 == -h ]]; then
        for i in ${!cd_history[@]}; do
            echo $i: "${cd_history[$i]}"
        done
        return
    elif [[ $1 =~ ^-[0-9]+ ]]; then
        builtin cd "${cd_history[${1//-}]}" || # Remove the argument's dash
        return 
    else
        builtin cd "$@" || return # Bail if cd fails
    fi
    # cd_history = ["", $OLDPWD, cd_history[1:]]
    cd_history=("" "$OLDPWD" "${cd_history[@]:1:${#cd_history[@]}}")
}

Điều này cũng có sẵn như là một GitHub Gist . Để sử dụng tính năng này, chỉ cần dán chức năng vào .bashrchoặc tương tự, và bạn sẽ có thể thực hiện những việc như cd -5quay lại thư mục thứ 5 cuối cùng mà bạn đã tham gia. cd -hSẽ cho bạn cái nhìn tổng quan về lịch sử của bạn.

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.