2009-04-24 26 views
240

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

Ví dụ: tôi có tệp nhị phân helloworld tạo tệp hello-world.txt trong thư mục hiện tại. Tệp này nằm 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/helloworld và nhận số hello-world.txt ở đâu đó trong thư mục thứ ba /c.

+4

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

Trả lời

406

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

(cd /c; /a/helloworld) 

Dấu ngoặc gây ra một sub-vỏ được sinh ra. Trình bao này sau đó thay đổi thư mục làm việc của nó thành /c, sau đó thực hiện helloworld từ /a. Sau khi chương trình thoát, sub-shell chấm dứt, đưa bạn trở lại dấu nhắc của shell cha, trong thư mục mà 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ụ: khi đã sai chính tả /c, làm cho việc thực hiện các helloworld có điều kiện:

(cd /c && /a/helloworld) 

Giảm sử dụng bộ nhớ: Để tránh việc bộ nhớ lãng phí subshell khi hello world thực hiện, gọi helloworld qua exec:

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

[ Cảm ơn Josh and Juliano vì đã đưa ra các mẹo cải thiện câu trả lời này!]

+1

Bất kỳ cách nào để chuyển đối số cho trình bao này? Như trong $ 1, và $ 2? – finiteloop

+1

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

+0

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

1

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

3

Một cách để làm điều đó là tạo tập lệnh trình bao bọc.

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

Dưới đây là một bash shell script ví dụ:

#!/bin/bash 
cd /c 
/a/helloworld 
14
sh -c 'cd /c && ../a/helloworld' 
+1

Sử dụng lệnh này cho jexec của FreeBSD để thực hiện lệnh bên trong tù trong thư mục làm việc được chỉ định. –

+0

wow ur may mắn họ thậm chí còn cho phép bạn sử dụng máy tính trong tù –

+0

@MattWilde https://www.freebsd.org/cgi/man.cgi?jail – mihi

77

Tương tự như câu trả lời David Schmitt 's, cộng với đề nghị của Josh, nhưng không để lại một quá trình shell chạy:

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

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

+0

[Bash manual builtins ** exec **] (https: // www .gnu.org/software/bash/manual/html_node/Bourne-Shell-Builtins.html # Bourne-Shell-Builtins) –

1

Nếu bạn muốn thực hiện điều này trong chương trình của bạn sau đó 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... 

} 
+0

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

9

Tôi luôn luôn nghĩ rằng các công cụ UNIX nên được viết như lọc, hãy đọc đầu vào từ stdin và viết ra để stdout. Nếu có thể bạn có thể thay đổi nhị phân helloworld của bạn để ghi nội dung của tập tin văn bản thành stdout hơn là một tập tin cụ thể. Bằng cách đó, bạn có thể sử dụng trình bao để viết tệp của mình ở bất kỳ đâu.

$ cd ~/b

$ ~/A/helloworld> ~/c/helloworld.txt

+5

+1 cho quyền, mặc dù câu trả lời chỉ là một câu trả lời ngoại vi. –

1

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

cd SOME_PATH && run_some_command && cd -

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

+0

Nó sẽ không đưa bạn trở lại nếu run_some_command thất bại. –

+0

Bạn đang viết @mezhaka, nên cân nhắc điều đó :) – Sahil

7

Một lựa chọn mà không đòi hỏi một subshell và được xây dựng trong để bash

(pushd SOME_PATH && run_stuff; popd) 

Demo:

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

Một gợi ý tương tự đã được thực hiện dưới đây bởi Sahil. 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_stuff thất bại, hơn popd sẽ không được thực hiện. –

+0

Trả lời trễ, tùy thuộc vào cài đặt của tệp bash. Bash có thể tiếp tục thực hiện 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 thiết lập để không làm điều đó bằng cách sử dụng '' set -e'' trong tập tin và sau đó nó sẽ không thành '' popd''. – Loren

+1

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

4

Chỉ cần thay đổi người cuối cùng "& &" thành ";" và nó cd sẽ trở lại cho dù lệnh thất bại hay thành công:

cd SOME_PATH && run_some_command ; cd - 
-1

từ thư mục hiện hành cung cấp đường dẫn đầy đủ đến thư mục kịch bản để thực hiện lệnh

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

Điều đó không thay đổi thư mục làm việc chút nào - 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. –

Các vấn đề liên quan