Thực hiện một lệnh cụ thể trong một thư mục nhất định mà không cd'ing nó?


42

Có cách nào để thực thi một lệnh trong một thư mục khác mà không cần phải thực cdhiện nó không? Tôi biết rằng tôi có thể chỉ đơn giản là cdtrong và cdra ngoài, nhưng tôi chỉ quan tâm đến các khả năng của ít ưu điểm hơn các bước thêm :)


Thật là tầm thường khi tạo ra một kịch bản thực hiện điều này : echo "#!/bin/bash; cd $1; exec $2" > /usr/local/bin/execindirectory; chmod +x /usr/local/bin/execindirectory. Có thể cần nỗ lực hơn một chút nếu bạn muốn nó thực sự hỗ trợ các "thẻ" tùy chọn, chẳng hạn như -dvà công cụ.
LawrenceC

Là một trạng thái không xác định người dùng trong câu trả lời, tất cả các ví dụ bạn đã đưa ra ở đây và trong các nhận xét đều được giải quyết tốt hơn bằng các giải pháp khác, vì vậy không rõ có thực sự có vấn đề cần giải quyết ở đây không. Bạn có thể đưa ra một ví dụ tốt hơn?
Caleb

Câu trả lời:


55

Tôi không biết nếu điều này được tính, nhưng bạn có thể tạo một subshell:

$ (cd /var/log && cp -- *.log ~/Desktop)

Thư mục chỉ được thay đổi cho lớp con đó, vì vậy bạn tránh được công việc cần thiết cd -sau đó.


2
Đó là những gì tôi thường làm.
Adam Byrtek

Thật tuyệt, tôi đã quên hoàn toàn về đạn pháo phụ, rất tiện dụng trong trường hợp này.
Naftuli Kay

4
Để tránh sự hỗn loạn tiềm ẩn, hãy bỏ dấu chấm phẩy bằng hai ký hiệu : $ (cd /var/log && cp *.log ~/Desktop). Theo cách đó, nếu thư mục không tồn tại, không có lệnh nào được thực thi nữa.
Naftuli Kay

Lưu ý cho bất kỳ ai khác ngây thơ như tôi: $ khi bắt đầu không phải là một phần của lệnh, chỉ là mọi thứ sau nó.
Maltronic

14

Một số chương trình có các tùy chọn mà bạn có thể yêu cầu chúng tự chdir (2) (ví dụ: GNU tar tựa s -C/ --directory).

Mặc dù bên ngoài các chương trình như vậy, một cái gì đó sẽ phải chdir . Bạn có thể viết và sử dụng một số loại chương trình BST nhị phân được biên dịch thay vì sử dụng shell, nhưng có lẽ nó sẽ không mang lại nhiều lợi ích.

Trong một bình luận trong một câu trả lời khác, bạn đã đưa ra một ví dụ:

execindirectory -d /var/log "cp *.log ~/Desktop"

*.logmẫu được mở rộng bằng chính shell (không phải cp ), nên một cái gì đó sẽ phải chdir vào thư mục trước khi có shell đánh giá lệnh của bạn.

Nếu bạn chỉ thú vị trong việc tránh phải quay lại cd cd, thì bạn có thể sử dụng một lớp con để tách hiệu ứng của cd khỏi thể hiện vỏ làm việc của bạn.

(cd /path/to/dir && some command)

Bạn có thể gói nó trong một hàm shell. (Tôi đã bỏ -dtùy chọn khỏi cách sử dụng ví dụ của bạn vì có rất ít điểm đến lệnh này nếu thư mục thực sự là tùy chọn.)

runindir() { (cd "$1" && shift && eval "$@"); }

runindir /var/log 'cp *.log ~/Desktop'  # your example
runindir /var/log cp \*.log \~/Desktop  # eval takes multiple args

runindir /var/log cp \*.log ~/Desktop   # it is okay to expand tilde first

2
Tôi thích giải pháp này, ngoại trừ, cá nhân tôi sẽ sử dụng Pushd / popd
NJ

10

Không làm giảm giá trị của câu trả lời được đưa ra bởi người khác, nhưng tôi tin rằng những gì bạn muốn là đây:

(cd /path/to && ./executable [ARGS])

Lưu ý các parens để gọi cdtrong một vỏ phụ.


Tôi không nghĩ vậy. Theo tôi hiểu, anh ấy muốn kết thúc trong thư mục ban đầu.
Adam Byrtek

Ồ, tôi hoàn toàn quên bọc nó vào vỏ phụ. Sửa câu trả lời của tôi, cảm ơn bạn.
alex

4

Đây là một cái gì đó sẽ cho phép bạn cdtrở lại nơi bạn đã ở (sử dụng Bash), vì không quên làm như vậy dường như là mục đích của câu hỏi:

# Save where you are and cd to other dir
pushd /path/to/dir/that/needs/to/be/current/dir

run-your-command

# Get back where you were at the beginning.
popd

(EDIT: phiên bản ngắn hơn một chút, nhờ @ Random832)


1
bạn chỉ có thể pushd other-dir, chứ không phảipushd .; cd other-dir
Random832

@ Random832, điểm tốt!
Bruno

2

Đáng buồn thay, ví dụ của bạn:

execindirectory -d /var/log "cp *.log ~/Desktop"

không cần thay đổi thư mục, bởi vì

cp /var/log/*.log ~/Desktop

sẽ làm như vậy. Bạn có thể đến gần hơn với vấn đề thực sự của bạn? Bởi vì chúng ta có thể biết một giải pháp tốt hơn cho điều đó quá.

Một cách phức tạp để giải quyết vấn đề của bạn, khác xa với sự thanh lịch của giải pháp Michaels, là sử dụng công cụ tìm kiếm, có công tắc '-execdir' được thực hiện trong thư mục, nơi tìm thấy tệp. Áp dụng không tốt cho ví dụ của bạn:

find /var/log -maxdepth 1 -type f -name "*.log" -execdir echo cp {} ~/Desktop ";"

Có lẽ nó hữu ích cho vấn đề thực sự của bạn. -okdir thay vì -execdir sẽ yêu cầu bạn xác nhận mọi lời mời.

-okdir và -execdir có thể cần cài đặt gnu-find, thường được sử dụng trên Linux.


1

Thế còn ./your/path/command.sh?


Không, tôi thực sự có ý nghĩa như sau : execindirectory -d /var/log "cp *.log ~/Desktop".
Naftuli Kay

Nhân tiện, tôi hoàn toàn biết rằng điều này không thực sự cần thiết, nhân tiện, tôi chỉ quan tâm đến việc nó có thực sự được thực hiện hay không.
Naftuli Kay
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.