Làm cách nào để chạy một chương trình với một thư mục làm việc khác với hiện tại, từ Linux shell?


352

Sử dụng shell Linux , làm cách nào để bắt đầu một chương trình với một thư mục làm việc khác với thư mục làm việc hiện tại?

Ví dụ, tôi có một tệp nhị phân helloworldtạo tệp hello-world.txttrong thư mục hiện tại .

Tập tin này là bên trong thư mục /a.

Hiện tại, tôi đang ở trong thư mục /b. Tôi muốn bắt đầu chương trình của mình chạy ../a/helloworldvà lấy hello-world.txtmột nơi nào đó trong thư mục thứ ba /c.


5
Tôi phát hiện ra một cách khó khăn để suđặt lại thư mục làm việc vào thư mục chính của người dùng mà bạn chỉ định trước khi chạy bất kỳ -clệnh nào . Điều này rất hữu ích với tôi.
Patrick M

Câu trả lời:


561

Gọi chương trình như thế này:

(cd /c; /a/helloworld)

Các dấu ngoặc đơn làm cho một lớp vỏ phụ được sinh ra. Lớp vỏ phụ này sau đó thay đổi thư mục làm việc của nó thành /c, sau đó thực thi helloworldtừ /a. Sau khi chương trình thoát, shell phụ chấm dứt, đưa bạn trở lại dấu nhắc của shell cha, trong thư mục bạn đã bắt đầu.

Xử lý lỗi: Để tránh chạy chương trình mà không thay đổi thư mục, ví dụ như khi viết sai chính tả /c, hãy thực hiện helloworldđiều kiện:

(cd /c && /a/helloworld)

Giảm mức sử dụng bộ nhớ: Để tránh việc có bộ nhớ thải phụ trong khi hello world thực thi, hãy gọi helloworldqua exec:

(cd /c && exec /a/helloworld)

[Cảm ơn Josh và Juliano đã cho lời khuyên về việc cải thiện câu trả lời này!]


1
Bất kỳ cách nào để truyền đối số cho shell này? Như trong $ 1, và $ 2?
finiteloop

2
@segfault: Subshell có quyền truy cập hoàn toàn vào phạm vi xung quanh.
David Schmitt

Có vẻ như nó tạm thời nằm trong thư mục đó, phải không?
dhein

1
Bạn có thể vượt qua tất cả các đối số bằng cách thực hiện $ *, $ @ hoặc "$ @" (nếu bạn muốn các đối số tôn trọng dấu ngoặc kép)
Marcel Valdez Orozco

1
Nó sẽ hoạt động nếu tôi thêm dòng này vào /etc/rc.d/rc.local?
Pratik Patil

95

Tương tự như câu trả lời của David Schmitt , cộng với gợi ý của Josh, nhưng không để lại một quy trình vỏ đang chạy:

(cd /c && exec /a/helloworld)

Cách này tương tự như cách bạn thường chạy các lệnh trên shell. Để thấy sự khác biệt thực tế, bạn phải chạy ps eftừ một vỏ khác với mỗi giải pháp.



25

Một tùy chọn không yêu cầu một lớp con và được tích hợp để bash

(pushd SOME_PATH && run_stuff; popd)

Bản giới thiệu:

$ pwd
/home/abhijit
$ pushd /tmp # directory changed
$ pwd
/tmp
$ popd
$ pwd
/home/abhijit

1
Một gợi ý tương tự đã được Sahil thực hiện dưới đây. Nó không hoạt động nếu lệnh thất bại. Hãy xem xét pushd SOME_PATH && run_stuff && popd- nếu run_ ware thất bại, thì popd sẽ không được thực thi.
Anton Daneyko

Trả lời trễ, điều đó phụ thuộc vào cài đặt của tệp bash. Bash có thể tiếp tục thực thi các lệnh ngay cả sau khi một lệnh thất bại (không giống như sử dụng &&), nhưng nó có thể được đặt thành không làm điều đó bằng cách sử dụng set -etrong tệp và sau đó nó sẽ thất bại popd.
Loren

8
Tuy nhiên, tôi nghĩ pushd "${SOME_PATH}" && run_stuff; popdlà tốt hơn so với câu trả lời hiện tại, vì ngữ nghĩa Pushd / popd được thiết kế đặc biệt cho tình huống này để đi vào thư mục nào đó và sau đó quay lại bản gốc.
Marcel Valdez Orozco

Làm thế nào để nó hoạt động như được định nghĩa là bí danh và tôi cần phải vượt qua một param?
DrB

Tôi nghĩ rằng bạn cần phải viết một tập lệnh shell mà bạn sẽ truyền tham số sẽ thực thi chuỗi lệnh vì bạn không thể truyền tham số ở giữa bí danh. Nếu bạn cần trợ giúp để viết điều đó, bạn nên đặt một câu hỏi riêng và tham khảo câu hỏi này. Khi bạn có tập lệnh shell, bạn có thể viết bí danh để gọi tập lệnh mới của mình.
Loren

19
sh -c 'cd /c && ../a/helloworld'

1
Đã sử dụng điều này cho jexec của FreeBSD để thực thi một lệnh bên trong tù trong thư mục làm việc được chỉ định.
Marián erný

11

Tôi luôn nghĩ rằng các công cụ UNIX nên được viết dưới dạng các bộ lọc, đọc đầu vào từ stdin và ghi đầu ra vào thiết bị xuất chuẩn. Nếu có thể, bạn có thể thay đổi tệp nhị phân hellowworld của mình để ghi nội dung của tệp văn bản vào thiết bị xuất chuẩn hơn là một tệp cụ thể. Bằng cách đó bạn có thể sử dụng shell để ghi tệp của mình ở bất cứ đâu.

$ cd ~ / b

$ ~ / a / hellowworld> ~ / c / helloworld.txt


6
+1 là đúng, mặc dù câu trả lời chỉ là câu trả lời ngoại biên.
David Schmitt

8

Chỉ cần thay đổi "&&" cuối cùng thành ";" và nó sẽ cd trở lại bất kể nếu lệnh thất bại hoặc thành công:

cd SOME_PATH && run_some_command ; cd -

4

Một cách để làm điều đó là tạo một tập lệnh shell shell.

Kịch bản shell sẽ thay đổi thư mục hiện tại thành / c, sau đó chạy / a / helloworld. Khi kịch bản shell thoát ra, thư mục hiện tại sẽ trở lại / b.

Đây là một ví dụ kịch bản bash shell:

#!/bin/bash
cd /c
/a/helloworld

2

tại sao không giữ nó đơn giản

cd SOME_PATH && run_some_command && cd -

lệnh 'cd' cuối cùng sẽ đưa bạn trở lại thư mục pwd cuối cùng. Điều này sẽ làm việc trên tất cả các hệ thống * nix.


Bạn đang viết @mezhaka, nên xem xét điều đó :)
Sahil

1
Cảnh báo: Nếu run_some_commandthất bại, cd -sẽ không được thực thi.
starbeamrainbowlabs

1

Nếu bạn luôn muốn nó đi đến / C, hãy sử dụng một đường dẫn tuyệt đối khi bạn viết tệp.


0

Nếu bạn muốn thực hiện điều này trong chương trình của bạn thì tôi sẽ làm một cái gì đó như:

#include <unistd.h>
int main()
{
  if(chdir("/c") < 0 )  
  {
     printf("Failed\n");
     return -1 ;
  }

  // rest of your program...

}

Anh ta muốn làm điều đó trong một kịch bản shell chứ không phải trong C. Ngoài ra, sẽ là một ý tưởng khủng khiếp để xử lý tệp nhị phân.

-1

từ thư mục hiện tại cung cấp đường dẫn đầy đủ đến thư mục script để thực thi lệnh

/root/server/user/home/bin/script.sh

1
Điều đó hoàn toàn không thay đổi thư mục làm việc - Tôi nghĩ bạn đang trả lời một câu hỏi khác với câu hỏi đã được hỏi.
Toby Speight

Đến đây để tìm câu trả lời cho câu hỏi bạn đã trả lời. Cảm ơn! lol
kfrncs
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.