Tại sao không có cd cd làm việc trong một kịch bản shell?


43

Tôi chỉ muốn viết một kịch bản thay đổi thư mục của tôi .

Tôi đặt các lệnh dưới đây trong tập tin /home/alex/pathABC

#!/bin/sh
cd /home/alex/Documents/A/B/C
echo HelloWorld

Tôi đã làm chmod +x pathABC.

Trong terminal, trong khi vào /home/alex, tôi chạy ./pathABC, nhưng đầu ra chỉ HelloWorldvà thư mục hiện tại không thay đổi.

Vậy điều gì là sai?


Câu trả lời:


74

Như những người khác đã giải thích, thư mục được thay đổi trong quy trình con của tập lệnh của bạn, không phải trong quy trình đầu cuối mà tập lệnh được gọi. Sau khi tiến trình con chết, bạn quay trở lại thiết bị đầu cuối còn lại ở đó.

Một số lựa chọn thay thế:

1. Liên kết tượng trưng

Đặt một liên kết tượng trưng trong nhà của bạn đến con đường dài bạn muốn dễ dàng truy cập

$ ln -s /home/alex/Documents/A/B/C ~/pathABC

sau đó truy cập vào thư mục với:

$ cd ~/pathABC

2. Bí danh

Đặt bí danh trong ~ / .bashrc:

alias pathABC="cd /home/alex/Documents/A/B/C"

(từ đây )

3. Chức năng

Tạo một chức năng thay đổi thư mục, chức năng chạy trong quá trình của thiết bị đầu cuối của bạn và sau đó có thể thay đổi thư mục của nó.

(từ đây )

4. Tránh chạy khi còn nhỏ

Nguồn kịch bản của bạn thay vì chạy nó. Tìm nguồn cung ứng (được thực hiện bởi .hoặc source) làm cho tập lệnh được thực thi trong cùng một vỏ thay vì chạy trong lớp con của chính nó.

$ . ./pathABC

(từ đâyđây )

5. vars có thể cd

Đặt cdable_varstùy chọn trong của bạn ~/.bashrcvà tạo một biến môi trường cho thư mục:

shopt -s cdable_vars
export pathABC="/home/alex/Documents/A/B/C"

Sau đó, bạn có thể sử dụng cd pathABC

(từ đây )


15
Bây giờ tôi hiểu cách sử dụng source! Tôi luôn tự hỏi tại sao tôi làm source .bashrcvà khôngbash .bashrc
hytromo

Lựa chọn 3 làm việc tuyệt vời. Tôi chỉ định nghĩa một hàm go_to_wherever () {cd my / thư mục} ở đầu tập lệnh của tôi. Gọi nó trước khi chạy các hoạt động trong thư mục đó.
i2097i

> 5. vars có khả năng cd - không phải là nó cd $pathABC?
loxaxs

7

Khi bạn chạy tập lệnh trong một thiết bị đầu cuối, một tiến trình con sẽ chạy. Trong chương trình con này, tức là tập lệnh của bạn sẽ thay đổi thành bất kỳ thư mục nào được chỉ định. Nhưng trong tiến trình cha mẹ tức là nơi bạn chạy tập lệnh vẫn nằm trong đường dẫn cũ. HOẶC đơn giản là chúng ta có thể nói:

The scope of cd command is only for child process not parent


2
Thêm vào đó, @ Alex để đạt được hiệu quả bạn đang tìm kiếm, thực thi kịch bản trong quá trình cha mẹ bằng cách tìm nguồn cung ứng nó: hoặc . pathABChoặc source pathABC.
zwets

4

Bạn đang làm cho một lỗi suy nghĩ. Trong khi shell hiện tại vẫn nằm trong cùng thư mục, tập lệnh đã chuyển sang thư mục mới.

Bạn có thể thấy điều đó bằng cách tạo một tập lệnh khác trong thư mục mới và chạy nó từ tập lệnh của bạn, sau khi nó đã thay đổi thư mục:

#!/bin/sh
cd /home/alex/Documents/A/B/C && ./another_script.sh # (if it is executable)

Kịch bản thứ hai sẽ chạy từ thư mục mới.

HelloWorld 

chỉ là đầu ra của kịch bản.


3
HelloWorld không được "trả lại" cho shell cha, nó xuất ra đầu ra tiêu chuẩn
Mog

Có thể rõ ràng hơn nếu bạn chỉ chạy pwdtrong thư mục mới, thay vì thêm một tập lệnh hoàn toàn mới vào tình huống.
wjandrea

0

Bởi vì thế giới xin chào chỉ là một tuyên bố dấu vết, chúng ta hãy thử điều này:

Tạo tập tin bash cd.shchứa:

#!/bin/bash
echo "/home/mike/Documents/A/B/C"
  • Phần .shmở rộng là một quy ước cũ hơn về việc cung cấp tập lệnh bash tên tập tin mở rộng. Đó hoàn toàn là mỹ phẩm và thường không cần thiết. Tuy nhiên trong trường hợp này, điều quan trọng là phải phân biệt với cdlệnh cốt lõi .

Đánh dấu tệp bash script thực thi bằng cách sử dụng:

chmod a+x cd.sh

Bây giờ chạy tệp:

$ cd $(./cd.sh)
bash: cd: /home/alex/Documents/A/B/C: No such file or directory
  • cd chúng ta đều biết
  • $(...) thực thi lệnh bên trong dấu ngoặc đơn và trả về đầu ra.
  • Nếu cd.shtrong đường dẫn của bạn, bạn không cần chỉ định nó ở đâu. Chúng tôi tiền tố ./để chỉ định lệnh là trong thư mục hiện tại.
  • Đầu echora từ cd.shtập lệnh được gửi lại cho cha mẹ thông qua $(...). Phụ huynh (dấu nhắc shell của chúng tôi) sử dụng đầu ra này và chuyển nó tới cdlệnh Linux .

Như những người khác đã đề cập đến một quá trình con không thể thay đổi thư mục của cha mẹ. Đây là một cách đứa trẻ có thể nói cho cha mẹ biết nơi để đi sau khi quá trình kết thúc.


@wjandrea Đó là những gì bạn nhận được để mã hóa trên điện thoại! Vừa về đến nhà, tôi sẽ sửa nó. Cảm ơn. Um chỉ cần kiểm tra và nó hoạt động tốt. Có lẽ đó là 14.04phiên bản của bạn tôi đọc khoảng một giờ trước hoặc lâu hơn?
WinEunuuchs2Unix

Vâng, bạn hoàn toàn thay đổi kịch bản. Trước đây, nó chỉ là một lệnh : cd /home/mike/Documents/A/B/C, không tạo ra bất kỳ đầu ra nào. Bây giờ echo "/home/mike/Documents/A/B/C", nó tạo ra đầu ra.
wjandrea

@wjandrea Đúng vậy, tôi cũng thay đổi hoàn toàn cách gọi kịch bản. Thay vì đơn giản ./cd.shnhư bây giờ cd $(./cd.sh)nhưng nó hoàn thành mục tiêu của đứa trẻ thay đổi thư mục hiện tại của cha mẹ. Vâng, đó là thông thường nhưng đó là một cách làm khác mà tôi hy vọng mọi người thấy thú vị.
WinEunuuchs2Unix
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.