2011-05-25 36 views
8

Tôi muốn biết nếu có thể thay đổi thư mục thiết bị đầu cuối hiện tại từ nơi tôi đang thực thi kịch bản ruby ​​của mình.Làm thế nào để (thiết bị đầu cuối) cd trong thư mục từ kịch bản ruby ​​

Ví dụ: nếu tôi đang thực thi tập lệnh từ $HOME trong thiết bị đầu cuối, tôi muốn cd ở $HOME/mydir ở cuối tập lệnh.

Tôi đã thử một vài điều, nhưng tôi luôn tìm kiếm trong cùng một bộ phim mà kịch bản được bắt đầu.

Những điều tôi đã cố gắng:

Dir.chdir(mydir) 
%[cd mydir] 

Họ thực sự làm thay đổi thư mục, nhưng chỉ trong các chủ đề của việc thực hiện kịch bản. Khi kịch bản kết thúc, vị trí hiện tại của tôi trong thiết bị đầu cuối vẫn như cũ trước khi khởi chạy tập lệnh.

Tôi đã tìm thấy điều gì đó tương tự trong SO, nhưng đó là Python-related và phản hồi có vẻ tiêu cực.


Bạn có thể hỏi tại sao?

Tôi hiện đang tham gia vào một ứng dụng dòng lệnh (sử dụng gli) mà, như điểm bắt đầu, cần một thư mục dự án. Vì vậy, lệnh đầu tiên của tôi trông giống như:

$ myfoo new project 

Tạo thư mục mới có tên project trong thư mục hiện tại. Bây giờ để có thể làm việc với các lệnh khác tôi cần phải:

$ cd project 
project$ myfoo domore 

Vì vậy, tôi đã đơn giản nghĩ rằng nó sẽ được tốt đẹp để tìm thấy tự của tôi trong project sau khi đã thực hiện myfoo new project.


Như tôi đã sợ, nó không phải là dễ dàng (không thể). Vì vậy, những gì về cách sử dụng một kịch bản bash mà ruby ​​gọi là tôi muốn, thay cho tập tin chuẩn được tạo ra bởi RubyGems? Điều đó có khả thi không? Tôi có ngu ngốc không? Tôi có nên sử dụng eval không?


Cảm ơn câu trả lời. Nhưng tôi sợ rằng không ai được chấp nhận. Có lẽ câu hỏi không phải là :).

+0

Có vẻ như bạn sẽ không thể thực hiện việc này. Bất kỳ lời gọi hệ thống nào từ ruby ​​đều hoạt động trong một luồng khác từ tập lệnh/trình bao của bạn và sẽ không ảnh hưởng đến vị trí hiện tại. Bạn đang hy vọng sử dụng điều này để làm gì? –

+0

@ Douglas-F-Shearer: Tôi đã mở rộng lý do của tôi một chút trong câu trả lời –

+0

chỉ vì tò mò, tại sao câu trả lời của tôi không hoạt động? Tôi đã sử dụng kỹ thuật này một vài lần, và tôi không rõ làm thế nào nó không phù hợp với tình hình của bạn. – Ian

Trả lời

2

Điều này là không thể, theo hiểu biết của tôi, vì chúng là các quy trình khác nhau. Nếu bạn cần phải ảnh hưởng đến quá trình cha mẹ của tập lệnh Ruby (Bash), Bash sẽ cần phải mã nguồn thứ gì đó. Vì vậy, bạn có thể có kịch bản lệnh Ruby của bạn xuất ra một số lệnh bash, sau đó có một trình bao bọc Bash là kết quả đầu ra của Ruby.

Hãy thử điều này làm ví dụ, trong Bash:

`ruby -e 'puts "cd /tmp"'` | source /dev/stdin 

But this will only work in Bash 4.0.

EDIT:

Trên thực tế, bạn có thể làm điều này với eval thay vì nguồn trong Bash 3:

eval $(ruby -e'puts "cd /tmp"') 
+0

Ok, nhưng tôi kết thúc trong kịch bản của mình với '% [eval $ (ruby -e'puts" cd/tmp "')]', mà không tạo ra bất kỳ sự khác biệt nào. –

+0

đúng, vì bạn đang sinh ra một quá trình Bash con (một đứa cháu của quá trình Bash bạn muốn ảnh hưởng), đánh giá mã của bạn trong đó, và sau đó để nó chết. Bạn cần phải chạy eval trực tiếp trong quá trình Bash mà bạn muốn thay đổi. Sau đó, bạn có thể dọn dẹp nó bằng bí danh hoặc một cái gì đó. – Ian

+0

Tôi đã mở rộng câu trả lời hỏi câu hỏi theo cách khác. –

2

Tôi nghi ngờ có một cách đơn giản để thực hiện việc này.

Khi bạn khởi động chương trình từ trình bao đăng nhập, bên dưới bảng điều khiển, nó thực hiện một quy trình mới (con) được tạo (có môi trường riêng, chẳng hạn như thư mục làm việc hiện tại) và đầu vào tiêu chuẩn/output/lỗi stream được kết hợp với quá trình shell (parent). Vì vậy, khi kịch bản của bạn gọi Dir.chdir nó thay đổi thư mục làm việc hiện tại cho quá trình kịch bản (con), không phải là phụ huynh.

Có lẽ tập lệnh của bạn có thể khởi chạy một vỏ mới trước khi thoát, vì vậy có vẻ như thiết bị đầu cuối của bạn đã thay đổi thư mục. Mặc dù, bạn phải thoát khỏi lớp vỏ thừa đó trước khi thoát khỏi phiên đầu cuối của mình ...

+0

Tôi đã mở rộng câu trả lời hỏi câu hỏi theo cách khác. –

0

Midnight Commander thực hiện việc này bằng cách sử dụng bí danh vỏ và tập lệnh bao bọc.

Trình bao bọc dành cho cd'ing vào thư mục được xác định bởi nội dung của tệp được viết bởi mc (1) tại lối ra và bí danh được sử dụng để source trình bao bọc. của subshell có thể đã được chia nhỏ, có kịch bản được đưa ra bình thường.

Tất cả trong tất cả, điều này cho phép nó thay đổi thư mục làm việc hiện tại khi thoát.

Để thực hiện việc này, bạn cần phải sao chép chức năng bí danh/trình bao bọc. Xem http://midnight-commander.org/browser/contrib để biết cách họ đã thực hiện.

+0

Có một số tài liệu về không? Làm cách nào để áp dụng điều này cho trường hợp sử dụng của tôi? –

+0

điều này giống như câu trả lời của tôi. – Ian

1

Có thể hơi dễ dàng hơn,

Bạn có thể sử dụng lệnh exec kết hợp với bài đăng Maerics về cách tạo vỏ bash mới bên trong ruby ​​để đạt được điều này.

exec ruby -e "Dir.chdir('mydir'); exec 'bash'" 

exec sẽ thay thế quá trình cha mẹ (vỏ) với quá trình con (ruby), do đó vỏ không còn tồn tại (không cần phải thoát ra).

Vào cuối của bash thường lệ ruby ​​được kích hoạt (một lần nữa với exec lần này trong ruby) trong thư mục mới và thay thế quy trình ruby.

+0

Làm cách nào để tích hợp nó với rubygem có lệnh riêng của nó, giống như câu lệnh được mô tả trong câu trả lời? –

+0

@empo Vào cuối tập lệnh ruby ​​thêm 'exec 'bash''. Từ dòng lệnh, sửa đổi lời gọi thành 'exec myfoo new project'. Điều này vẫn còn clunky mặc dù :( – diedthreetimes

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