Chỉ hiển thị thư mục hiện tại và thư mục mẹ trong dấu nhắc bash


16

Tôi mới sử dụng bash và muốn lời nhắc của tôi để hiển thị một cái gì đó trong tcsh là tầm thường, nhưng sau khi tìm kiếm google tốt, tôi vẫn không thể làm được.

Tôi muốn lời nhắc của tôi chỉ bao gồm các thư mục hiện tại và cha mẹ như thế này:

/parent/currentdir $

Trong tcsh điều này đạt được bằng cách:

set prompt = "%C2 %"

Tuy nhiên trong bash cho đến nay tôi chỉ thấy rằng tôi phải phân tích pwd để có được đầu ra tương tự.

Không có cách nào đơn giản hơn, như làm:

export PS1="$(some_command) $" 

2
Về lý thuyết, PS1='\w \$'; PROMPT_DIRTRIM=2sẽ cung cấp cho bạn bash tương đương, nhưng điều đó không hoạt động đúng trên hệ thống của tôi.
Mikel

Nó hoàn toàn không hoạt động với tôi: GNU bash, phiên bản 3.2.57 (1) -release (x86_64-apple-darwin14).
twalbaum

PROMPT_DIRTRIMđã được giới thiệu trong Bash 4 . Tôi mới thử nghiệm trên Ubuntu 16.04 theo WSL và nó hoạt động rất tốt!
Mike Branski

Câu trả lời:


18

Các tính năng điều khiển nhanh chóng của Bash khá tĩnh. Nếu bạn muốn kiểm soát nhiều hơn, bạn có thể bao gồm các biến trong lời nhắc của mình; đảm bảo bạn chưa tắt promptvarstùy chọn .

PS1='${PWD#"${PWD%/*/*}/"} \$ '

Lưu ý các dấu ngoặc đơn: việc mở rộng biến phải xảy ra tại thời điểm dấu nhắc được hiển thị, không phải tại thời điểm PS1biến được xác định.

Nếu bạn muốn kiểm soát nhiều hơn những gì được hiển thị, bạn có thể sử dụng thay thế lệnh. Ví dụ: đoạn trích ở trên mất ~chữ viết tắt cho thư mục chính.

PS1='$(case $PWD in
        $HOME) HPWD="~";;
        $HOME/*/*) HPWD="${PWD#"${PWD%/*/*}/"}";;
        $HOME/*) HPWD="~/${PWD##*/}";;
        /*/*/*) HPWD="${PWD#"${PWD%/*/*}/"}";;
        *) HPWD="$PWD";;
      esac; printf %s "$HPWD") \$ '

Mã này khá cồng kềnh, vì vậy thay vì dán nó vào PS1biến, bạn có thể sử dụng PROMPT_COMMANDbiến để chạy mã để đặt HPWDvà sau đó sử dụng mã đó trong lời nhắc của bạn.

PROMPT_COMMAND='case $PWD in
        $HOME) HPWD="~";;
        $HOME/*/*) HPWD="${PWD#"${PWD%/*/*}/"}";;
        $HOME/*) HPWD="~/${PWD##*/}";;
        /*/*/*) HPWD="${PWD#"${PWD%/*/*}/"}";;
        *) HPWD="$PWD";;
      esac'
PS1='$HPWD \$'

Vì lời nhắc rút ngắn chỉ thay đổi khi thay đổi thư mục, bạn không cần tính toán lại mỗi khi lời nhắc được hiển thị. Bash không cung cấp một hook chạy trên một thay đổi thư mục hiện tại, nhưng bạn có thể mô phỏng nó bằng cách ghi đè cdvà anh em họ của nó.

cd () { builtin cd "$@" && chpwd; }
pushd () { builtin pushd "$@" && chpwd; }
popd () { builtin popd "$@" && chpwd; }
chpwd () {
  case $PWD in
    $HOME) HPWD="~";;
    $HOME/*/*) HPWD="${PWD#"${PWD%/*/*}/"}";;
    $HOME/*) HPWD="~/${PWD##*/}";;
    /*/*/*) HPWD="${PWD#"${PWD%/*/*}/"}";;
    *) HPWD="$PWD";;
  esac
}
PS1='$HPWD \$'

Lưu ý rằng bạn không cần và không nên xuất PS1vì đây là cài đặt shell chứ không phải biến môi trường. Một PS1thiết lập bash sẽ không được hiểu bởi các shell khác.

PS Nếu bạn muốn có trải nghiệm vỏ tương tác đẹp, hãy chuyển sang zsh , trong đó tất cả những điều này ( %mở rộng nhanh chóng bao gồm phần lớn tcsh chpwd, v.v.) là các tính năng gốc.

PS1='%2~ %# '

2
Đây phải là câu trả lời được chấp nhận và nâng cao nhất.
LarsH

2

Cú pháp để lấy thư mục gốc và thư mục hiện tại được lấy từ Munai câu trả lời .

Tuy nhiên, như Gilles lưu ý, mã đó chỉ hiển thị thư mục hiện tại tại thời điểm .bashrcđược tải, nhưng nó sẽ không thay đổi khi bạn điều hướng hệ thống đến các thư mục khác.

Có điều này trong .bashrctệp của bạn làm cho lời nhắc tự động cập nhật vào thư mục hiện tại của bạn:

prompt_command () {
    PS1='$(basename $(dirname "$PWD"))/$(basename "$PWD") $ '
}
PROMPT_COMMAND=prompt_command

1
Là xác định prompt_command()phải làm một cái gì đó, trên chính nó? Nó không dành cho tôi. Bạn có nghĩa là cũng sử dụng prompt_command()để xác định lại cd& &, như Gilles đã làm? Hay ý bạn là PROMPT_COMMAND='...'gì?
LarsH

2
Ngoài ra, lệnh này thất bại khi $PWDchứa một khoảng trắng.
LarsH

1
Cảm ơn bạn đã đưa tôi trở lại này. Trích dẫn $ PWDs để cho phép khoảng trắng và bao gồm lệnh cuối cùng. Dấu nhắc hiện tại của tôi phức tạp hơn mức này, do đó cần định nghĩa prompt_command. Mặt khác, PS1 = ... hoạt động trên.
twalbaum

Bất kỳ ý tưởng để làm sạch đầu ra khi điều hướng đến /? Như đã viết, bạn nhận được/// $
ezrock

0

Chuỗi nhắc nhở có thể dễ dàng thay đổi bashbằng cách chỉnh sửa biến shell PS1. Nó là viết tắt của Prompt String 1. Thêm thông tin ở đây .

Để bây giờ cháy lên bashvỏ của bạn .

vi ~/.bashrc

Nối định nghĩa PS1 trong tệp

`export PS1="$(basename $(dirname $PWD))/$(basename $PWD)"`

Thêm hướng dẫn ở đâyđây , để giúp bạn tinh chỉnh nó nhiều hơn nữa.


1
Tôi hiểu làm thế nào để sửa đổi lời nhắc. Câu hỏi của tôi là làm thế nào để chỉ có các thư mục hiện tại và cha mẹ, không phải toàn bộ đường dẫn.
twalbaum

@twalbaum chỉnh sửa câu trả lời của tôi
Munai Das Udasin 18/07/2015

rất vui khi được giúp đỡ @twalbaum :)
Munai Das Udasin 18/07/2015

1
Điều này đặt lời nhắc đến thư mục hiện tại tại thời điểm .bashrcđược tải, lời nhắc sẽ không thay đổi nếu bạn cdvào thư mục khác! @twalbaum
Gilles 'SO- ngừng trở nên xấu xa'

@Gilles nó làm cho tôi.
twalbaum

0

Có thể đơn giản hơn với "~" cho thư mục Home.

function PWDN {
  echo "${PWD/#$HOME/~}" | rev | cut -d "/" -f1 -f2 | rev
}

0
export PS1='[\u@\h $(basename $(dirname ${PWD}))/$(basename ${PWD})]\$ '
export PROMPT_COMMAND='echo -ne "\033]0;$(basename $(dirname $PWD))/$(basename ${PWD})\007"'

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.