Làm thế nào để chạy một lệnh với một thư mục làm đối số, sau đó cd vào cùng? Tôi nhận được không có tập tin hoặc thư mục như vậy


15

Tôi muốn xây dựng một hàm ngắn để làm như sau. Giả sử tôi di chuyển tệp 'file.tex' vào thư mục tài liệu của mình:

mv file.tex ~/Documents

Sau đó, tôi muốn cdđến thư mục đó:

cd ~/Documents

Tôi muốn khái quát nó cho bất kỳ thư mục nào, để tôi có thể làm điều này:

mv file.tex ~/Documents
follow

và có followlệnh đọc đích từ lệnh trước, sau đó thực hiện theo. Đối với một thư mục đơn giản, điều này không tiết kiệm nhiều thời gian, nhưng khi làm việc với các thư mục lồng nhau, sẽ rất tuyệt vời khi chỉ có thể sử dụng

mv file.tex ~/Documents/folder1/subfolder1
follow

Tôi nghĩ nó sẽ tương đối đơn giản và tôi có thể làm một cái gì đó như thế này:

follow()
{
    place=`history 2 | sed -n '1p;1q' | rev | cut -d ' ' -f1 | rev`
    cd $place
}

nhưng điều này dường như không hoạt động. Nếu tôi lặp lại $place, tôi sẽ nhận được chuỗi mong muốn (tôi đang kiểm tra nó ~/Documents), nhưng lệnh cuối cùng trả về

No such file or directory

Thư mục chắc chắn tồn tại. Tôi thua lỗ. Ông có thể giúp tôi không?


Tôi muốn chỉ ra rằng nếu bạn không ngại giữ file.texvị trí ban đầu, các liên kết tượng trưng là một lựa chọn rất tốt, vì bạn chỉ phải liên kết một lần, và sau đó nó sẽ luôn trỏ đến phiên bản mới nhất.
Kroltan

5
Cách dễ dàng hơn: nhập cd alt + .để thay thế mã thông báo cuối cùng của lệnh trước đó. Lặp lại để quay trở lại trong lịch sử của các mã thông báo cuối cùng. (Tôi nói mã thông báo không phải là arg, vì foo &lấy &làm mã thông báo cuối cùng.) Bạn có thể sử dụng một đối số số (ví dụ với esc-3 alt +.).
Peter Cordes


Câu trả lời:


18

Thay vì xác định hàm, bạn có thể sử dụng biến $_được mở rộng thành đối số cuối cùng của lệnh trước đó bash. Vì vậy, sử dụng:

cd "$_"

sau khi ra mvlệnh.

Bạn cũng có thể sử dụng mở rộng lịch sử:

cd !:$

Nếu bạn phải sử dụng một chức năng:

follow () { cd "$_" ;}

$ follow () { cd "$_" ;}
$ mv foo.sh 'foo bar'
$ follow 
foo bar$ 

NB: Câu trả lời này được nhắm mục tiêu đến định dạng đối số dòng lệnh chính xác mà bạn đã sử dụng khi chúng tôi đang xử lý các tham số vị trí. Đối với các định dạng khác mv -t foo bar.txt, ví dụ , bạn cần kết hợp kiểm tra cụ thể trước đó, một trình bao bọc sẽ phù hợp sau đó.


Mở rộng lịch sử của bạn (cd !: $) Hoạt động hoàn hảo. Cảm ơn bạn. Tuy nhiên, cái khác (cd "$ _") không: mv file.tex ~ / Tải xuống / cd "$ _" bash: cd: __bp_preexec_invoke_exec: Không có tệp hoặc thư mục như vậy tôi sẽ rất vui lòng chấp nhận câu trả lời của bạn là hoàn toàn chính xác và cảm ơn bạn.
Cháy

Tôi đã luôn luôn gõ (hơi lãng phí) cd !$hoặc cd $(dirname !$). Không biết về $_biến!
Kalvin Lee

Bây giờ điều gì xảy ra nếu tôi làm mv -t ~/Documents file.texthay vì mv file.tex ~/Documents? Tóm lại, tôi không chắc điều này có thể giải quyết được trong trường hợp chung ... một chức năng bao bọc xung quanh hoặc các phần giới thiệu mvcó thể tốt hơn ...
một CVn

@ MichaelKjorling Sẽ không hoạt động đơn giản .. ví dụ này chỉ là để bao quát trường hợp OP có, chứ không phải các trường hợp cạnh (hoặc tất cả) ..
heemayl

Bạn không cần đại tràng; !$tương đương !:$và nhanh hơn để gõ.
tự đại diện

14

Với các phím bash tiêu chuẩn, tổ hợp Alt.sẽ sao chép đối số cuối cùng của dòng lệnh trước đó vào đối số hiện tại. Vì vậy, gõ

$ mv foo ~/some/long/path/
$ cd <Alt><.>

sẽ mang lại

$ mv foo ~/some/long/path/
$ cd ~/some/long/path/

và thậm chí sẽ ít gõ hơn từ follow.

Để thuận tiện hơn, việc lặp lại Alt.kết hợp sẽ duyệt qua các đối số cuối cùng của tất cả các dòng lệnh trước đó.

Phụ lục: Tên lệnh bash tương ứng với tổ hợp phím này là yank-last-arghoặc insert-last-argument. Nó có thể được tìm thấy trong trang bash dưới "Các lệnh thao túng lịch sử" hoặc trong Hướng dẫn tham khảo Bash đầy đủ hơn .)


1
Thật khéo léo. Cảm ơn! Tôi không có ý tưởng này tồn tại.
Cháy

@Fire Tôi đã thêm tài liệu tham khảo cho các lệnh đó, vì vậy bạn có thể tìm thấy các ràng buộc khóa thú vị hơn rất nhiều (và ngay lập tức quên chúng lại, như tôi luôn làm).
Dubu

1
Bạn cũng có thể sử dụng <esc>sau đó .để có được kết quả tương tự <alt>+., điều này hữu ích khi bạn đã ánh xạ lại capslock để thoát :)
gnur

1
@gnur vi (m) người dùng, tôi cho là vậy. ;-)
Dubu

6

Bạn gần như chắc chắn đang gặp phải vấn đề mở rộng dấu ngã xảy ra trước khi mở rộng tham số, có thể được giải thích bằng một ví dụ ngắn gọn:

$ cd ~kaz
kaz $ var='~kaz'
kaz $ echo $var
~kaz
kaz $ cd $kaz
bash: cd: ~kaz: No such file or directory

Điều này có thể được giải quyết với eval. Dù sao, bạn sẽ cần eval, bởi vì bạn đang rút các lệnh từ lịch sử và chúng có thể chứa các mở rộng tùy ý, như:

$ mv file.tex ~/Documents/$(compute_folder_name foo-param)/subfolder1
$ follow

(Có một số vấn đề, chẳng hạn như việc mở rộng lại các giá trị này có thể không còn phù hợp với việc mở rộng ban đầu đã xảy ra. Giả sử compute_folder_namelà một hàm làm tăng một số biến toàn cục.)


4
Bạn không cần eval. (Bao giờ.) Nhưng phát hiện tốt về các vấn đề trình tự mở rộng. Nếu bạn đề cập đến sự khuyến khích lớn hơn của việc mở rộng lịch sử khi sử dụng evalở đây, đây sẽ là câu trả lời tốt nhất theo ý kiến ​​của tôi; không ai trong số những người khác thực sự giải thích lý do tại sao giải pháp của Poster gốc không hoạt động.
tự đại diện
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.