Tập lệnh để thay đổi thư mục hiện tại (cd, pwd)


44

Tôi muốn chạy một kịch bản để thay đổi thư mục làm việc hiện tại:

#!/bin/bash
cd web/www/project

Nhưng, sau khi tôi chạy nó, pwd hiện tại vẫn không thay đổi! Làm thế nào tôi có thể làm điều đó?

Câu trả lời:


63

Đó là một hành vi dự kiến, và đã được thảo luận nhiều lần.

Kịch bản lệnh được chạy trong một lớp con và không thể thay đổi thư mục làm việc của lớp vỏ cha. Hiệu ứng của nó bị mất khi kết thúc.

Để thay đổi thư mục vĩnh viễn, bạn nên tìm nguồn script, như trong

. ./script

8
@Sony: Lưu ý rằng bạn nên sử dụng returnđể thoát khỏi tập lệnh có nguồn gốc theo cách này, chứ không phải exit- chúng giống như các hàm shell và exitsẽ thoát khỏi trình bao lấy tập lệnh.
Charles Stewart

@CharlesStewart Trên thực tế, tôi không quen thuộc với các tập lệnh có nguồn gốc. Cảm ơn bạn!
Sony Santos

5
source ./scriptgiống nhau không
amyassin

2
@amyassin: vâng, đúng vậy
enzotib

2
1. .sourcebằng nhau trong bash. 2. chúng ta không cần sử dụng ./trước tên tệp nếu nó nằm trong cùng thư mục. Chỉ có thể chạy cái này thôi:. script
sobi3ch

19

Đối với các tác vụ nhỏ như thế này, thay vì tạo tập lệnh, hãy tạo một bí danh như thế này,

$ alias cdproj='cd /dir/web/www/proj'

Bạn nên thêm nó vào .bashrctập tin của bạn , nếu bạn muốn nó được đặt cho mọi shell tương tác.

Bây giờ bạn có thể chạy này như $ cdproj.


1
Bạn cũng có thể có kịch bản lặp lại các lệnh sẽ được thực thi, sau đó sử dụng eval `./script` hoặc eval $(./script)để thực thi các lệnh đó. Đây là một cách tiếp cận phổ biến cho các lệnh cần cập nhật môi trường của shell shell.
Keith Thompson

2
Chỉ cần rất cẩn thận về những gì bạn đầu ra nếu bạn sẽ đi evaltiếp cận.
jw013

13

Sử dụng exec bashở cuối

Một tập lệnh bash hoạt động trên môi trường hiện tại của nó hoặc trên môi trường con cái của nó, nhưng không bao giờ trên môi trường cha mẹ của nó.

Tuy nhiên, câu hỏi này thường được hỏi vì người ta muốn để lại dấu nhắc bash trong một thư mục nhất định sau khi thực thi tập lệnh bash từ thư mục khác.

Nếu đây là trường hợp, chỉ cần thực hiện một cá thể bash con ở cuối tập lệnh:

#!/usr/bin/env bash
cd desired/directory
exec bash

Điều này tạo ra một subshell mới. Nhập exitđể trở về shell đầu tiên nơi kịch bản ban đầu được bắt đầu.


Tốt hơn là chỉ lấy nguồn kịch bản, như trong câu trả lời được chấp nhận: sử dụng execthường được coi là biện pháp cuối cùng của một kẻ vô lại .. :)
nơ ron

1
Thủ thuật này không hoạt động trong debian 9 căng.
vdegenne

3
Đây là cách sai lầm để đi về điều này!
Dennis Williamson

3
Vì không ai nêu chi tiết các vấn đề với điều này (tôi đang nhìn bạn, @Dennis): (1) Mỗi ​​lần bạn chạy nó, nó sẽ tạo ra một quy trình bash mới, liên tục. Thực hiện mười hoặc hai mươi lần trong một phiên và bạn sẽ có 11 đến 21 quy trình bash chồng chất. Điều này có thể ảnh hưởng đến hiệu suất và, nếu bạn cố gắng chấm dứt phiên một cách sạch sẽ bằng cách nhập exit(hoặc Ctrl + D), bạn sẽ phải làm điều đó từ 11 đến 21 lần. (2) Một nhược điểm khác của việc sử dụng tập lệnh thực thi là, nếu bạn đặt bất kỳ tùy chọn shell nào (ví dụ:  dotglobhoặc  globstar) trong phiên shell tương tác của mình, bạn sẽ mất chúng, bởi vì bạn đang bắt đầu một shell mới.
G-Man nói 'Phục hồi Monica'

1
Giải pháp rất hay! Tôi đã viết lại bí danh của mình trong bash_profile để bây giờ nó là một tập lệnh được lưu trữ trong một tệp riêng biệt. Tôi sử dụng tập lệnh để đi đến một thư mục tạm thời mới được tạo. Và bây giờ thậm chí còn dễ dàng hơn để có một phiên bash tạm thời. SRP đang hoạt động! Cảm ơn!
artyom.razinov

8

Mặc dù có những câu trả lời thực hiện hành động chính xác mà bạn muốn, một phương pháp chuẩn hơn cho mục đích đó là tạo liên kết tượng trưng:

ln -s ~/web/www/project proj   #use full path to dir!

Sau đó, bạn có thể cdvào thư mục bằng cách sử dụng tên proj:

cd proj

Phương pháp này linh hoạt hơn vì bạn có thể truy cập các tệp bằng tên ngắn mà không cần cd:

ls proj/   #note the endslash!
vim proj/file.x

4

Nếu bạn thay đổi giữa các thư mục ở xa trong hệ thống tập tin. Tôi sẽ đề nghị autojump .


4

Phụ thuộc vào những gì bạn sẽ làm, một giải pháp khác có thể là tạo một hàm thay vì một tập lệnh.

Thí dụ:

Tạo một hàm trong một tệp, giả sử /home/aidin/my-cd-script:

function my-cd() {
  cd /to/my/path
}

Sau đó đưa nó vào bashrchoặc zshrctập tin của bạn :

# Somewhere in rc file
source /home/aidin/my-cd-script

Bây giờ bạn có thể sử dụng nó như một lệnh:

$ my-cd

0

Tại sao không sử dụng "exec" nó đường nối để làm chính xác những gì tôi muốn.

#!/bin/bash

cd someplace
exec bash

~/someplace

1
Coi chừng những thứ dường như là những gì bạn muốn. (Một con ngựa gỗ khổng lồ! Đúng như những gì tôi muốn!) Mỗi ​​lần bạn chạy nó, nó tạo ra một quy trình bash mới, bền bỉ. Thực hiện mười hoặc hai mươi lần trong một phiên và bạn sẽ có 11 đến 21 quy trình bash xếp chồng lên nhau. Điều này có thể ảnh hưởng đến hiệu suất và, nếu bạn cố gắng chấm dứt phiên một cách sạch sẽ bằng cách nhập exit(hoặc Ctrl + D), bạn sẽ phải làm điều đó từ 11 đến 21 lần.
G-Man nói 'Phục hồi Monica'

Tôi chắc chắn có thể thấy nơi đó sẽ là một vấn đề. Đối với tôi mặc dù tôi đang sử dụng nó một lần, thực hiện công việc tôi cần và sau đó thoát ra. Nếu đó là nhược điểm duy nhất tôi có thể sống với điều đó. Mặt khác, nếu có một giải pháp tốt hơn, tôi sẵn sàng xem xét nó.
paul

Câu trả lời của Aidin cho câu hỏi này , sử dụng hàm shell và câu trả lời của Sachin Divekar , sử dụng bí danh, là (IMO) giải pháp tốt hơn so với sử dụng tập lệnh. PS Một nhược điểm khác của việc sử dụng tập lệnh là, nếu bạn đặt bất kỳ tùy chọn shell nào (ví dụ:  dotglobhoặc  globstar), bạn sẽ mất chúng, bởi vì bạn đang bắt đầu một shell mới. Tiết (Cont'd)
G-Man nói 'Tái lập lại Monica'

(Tiếp theo) Về PPS Tôi chỉ nhận thấy rằng, về cơ bản, bạn nhắc lại câu trả lời của Serge Stroobandt và nói '' Tại sao không làm điều này? '' Tại  Stack Exchange, chúng tôi hy vọng câu trả lời sẽ cung cấp ý tưởng và / hoặc thông tin mới, và không chỉ thảo luận câu trả lời khác.
G-Man nói 'Phục hồi Monica'

-1

Bạn có thể làm điều đó bằng cách sử dụng một hàm hoặc sử dụng && Các ví dụ dưới đây cài đặt Zabbix và tạo một tệp có một dòng bên trong nó.

Ví dụ:

#!/bin/bash

# Create Function:
installZabbix(){
    cd /usr/src/zabbix-4.2.4;
    ./configure --enable-agent;
    make install;
    cd /usr/src/;
    >file;
    echo "Hi, this is a file." >>file;
}

# Call the function:
installZabbix

hoặc là:

#!/bin/bash
cd /usr/src/zabbix-4.2.4 && ./configure --enable-agent && make install && cd /usr/src && >file && echo "Hi, this is a file." >>file
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.