Là sở hữu để thay đổi thư mục làm việc của shell cha theo chương trình?


8

Tôi muốn viết một số mã để cho phép tôi chuyển sang một số thư mục mà tôi thường đến. Nói rằng chương trình này là mycd, và /a/very/long/path/namelà thư mục mà tôi muốn đi đến.

Vì vậy, tôi chỉ có thể gõ mycd 2thay vì cd /a/very/long/path/name. Ở đây tôi giả sử mycdbiết 2đề cập đến điều đó /a/very/long/path/name. Cũng có thể mycd 1, mycd 3, ... vv

Vấn đề là tôi phải viết mycdnhư một tập lệnh shell và gõ . mycd 2để thực hiện điều mong muốn bởi vì nếu không thì tập lệnh chỉ được thực thi trong tập lệnh con mà không thay đổi bất cứ điều gì về trình bao cha mẹ mà tôi thực sự quan tâm.

Câu hỏi của tôi là:

  • Tôi có thể làm điều đó mà không cần sử dụng source? bởi vì . mycdgiả sử mycdphải là một kịch bản shell và điều này cũng có thể giới thiệu một số chức năng mà tôi không muốn.

  • Tôi có thể thực hiện nó trong một số ngôn ngữ lập trình khác không?

Câu trả lời:


23

tạo mycdmột hàm để cdlệnh thực thi trong shell hiện tại của bạn. Lưu nó trong tệp ~ / .bashrc của bạn.

function mycd {
    if (( $# == 0 )); then
        echo "usage: $FUNCNAME [1|2|3|...]"
        return
    fi
    case $1 in
        1) cd /tmp ;;
        2) cd /a/very/long/path/name ;;
        3) cd /some/where/else ;;
        *) echo "unknown parameter" ;;
    esac
}

Cảm ơn bạn, bạn đã không nghĩ đến việc sử dụng các chức năng và điều này chỉ cho phép mọi thứ: bây giờ tôi có thể mycdchuyển qua $@bất kỳ chương trình nào tôi thích.
Javran

Hãy chắc chắn rằng bạn trích dẫn "$@"để bất kỳ đối số có chứa khoảng trắng được xử lý chính xác.
glenn jackman

9

Bạn không thể thay đổi thư mục hiện tại của shell từ một quy trình khác. Chỉ có quá trình tự nó có thể thay đổi thư mục hiện tại của chính nó. Điều này cũng giữ cho một số đặc điểm khác như biến môi trường và mô tả tệp.

Thực sự có thể ảnh hưởng đến thư mục hiện tại của quy trình khác bằng cách khiến nó thực hiện chdircuộc gọi hệ thống thông qua ptracecuộc gọi hệ thống, đây là điều cho phép trình gỡ lỗi hoạt động. Tuy nhiên, nếu quá trình duy trì một số cấu trúc dữ liệu nội bộ phải phù hợp với thư mục hiện tại thực tế, chương trình có khả năng bị sập. Đối với một vỏ, cách tiếp cận này không có cơ hội để làm việc.

Bạn cần sắp xếp để mã của bạn được thực thi bởi chính shell. Cách tiến hành thông thường sẽ là biến nó thành một hàm shell và lưu trữ nó trong của bạn ~/.bashrc. Nếu điều này là không thể, ví dụ vì đó là mã mà bạn muốn phân phối, hãy viết tệp nguồn shell chứa định nghĩa hàm và yêu cầu mọi người để trình vỏ tương tác của họ đọc tệp của bạn bằng .lệnh .


1
Thực sự có một cơ hội để làm cho nó "hoạt động", nhưng nó không cần thiết, dễ bị lỗi và nên tránh bằng mọi giá. Để chỉ ra rằng nó thực sự là "có thể", hãy xem xét tập lệnh shell này trong đó cha mẹ là Bash : ws=$1; gdb -p $(ps h -o ppid -p $$) -ex "call chdir(\"$wd\")" -ex "call set_working_directory(\"$wd\")" -ex detach -ex q -batch. Thực thi như braindead-cd-parent /. Bạn sẽ thấy rằng pwdtrả lại /và như vậy ls, vv cư xử. Nhưng dấu nhắc ( PS1) vẫn không thay đổi, mắt mọi người bị tổn thương, v.v. Vì vậy, đừng làm điều này ngay cả khi có thể.
Lekensteyn

1
@Lekensteyn Đó là ptracephương pháp tôi đề cập. Nó hoạt động tốt trên các chương trình không quan tâm nhiều đến thư mục hiện tại của họ. Trong một hệ vỏ, rất nhiều thứ ( PWDbiến, dấu nhắc, v.v.) sẽ trở nên sai và vỏ có thể bị hỏng hoặc hoạt động sai.
Gilles 'SO- ngừng trở nên xấu xa'

5

Như bạn đã chỉ ra, các kịch bản shell luôn được thực thi trong một lớp con, điều này không thể ảnh hưởng đến trình bao mẹ của nó.

Tuy nhiên, bạn có thể ...

  • sử dụng bí danh:
    alias mycd2='cd /a/very/long/path/name'
  • có tập lệnh 1 của bạn xuất ra lệnh shell hợp lệ ...

    #!/bin/bash
    if [ "x$1" = "x2" ]
    then
        echo "cd /a/very/long/path/name"
    fi

    ... và thực hiện đầu ra của nó: $(mycd 2)

1: Bạn có thể muốn sử dụng một casetuyên bố hơn là ifđiều kiện trong ví dụ.


5
Một bí danh là có thể vượt qua. Một kịch bản là vấn đề tương tự anh ấy đã có. Câu hỏi này hét chức năng vỏ.
Ricky Beam
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.