Bagaimana menjalankan satu perintah dengan direktori sebagai argumen, lalu cd ke yang sama? Saya mendapatkan “tidak ada file atau direktori”

15

Saya ingin membuat fungsi singkat untuk melakukan hal berikut. Katakanlah saya memindahkan file 'file.tex' ke direktori dokumen saya:

mv file.tex ~/Documents

Lalu, saya ingin cdke direktori itu:

cd ~/Documents

Saya ingin menggeneralisasi ini ke direktori mana saja, sehingga saya bisa melakukan ini:

mv file.tex ~/Documents
follow

dan minta followperintah membaca tujuan dari perintah sebelumnya, kemudian jalankan sesuai. Untuk direktori sederhana, ini tidak menghemat banyak waktu, tetapi ketika bekerja dengan direktori bersarang, akan sangat luar biasa untuk dapat menggunakan saja

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

Saya pikir itu akan relatif sederhana, dan saya bisa melakukan sesuatu seperti ini:

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

tapi ini sepertinya tidak berhasil. Jika saya echo $place, saya mendapatkan string yang diinginkan (saya sedang menguji dengan ~/Documents), tetapi perintah terakhir kembali

No such file or directory

Direktori pasti ada. Saya bingung. Bisakah Anda membantu saya?

Api
sumber
Saya ingin menunjukkan bahwa jika Anda tidak keberatan menyimpan file.texdi lokasi asli, symlink adalah alternatif yang sangat baik, karena Anda hanya perlu menautkan satu kali, dan itu akan selalu mengarah ke versi terbaru.
Kroltan
5
Cara yang lebih mudah: ketik cd alt + .untuk mengganti token terakhir dari perintah sebelumnya. Ulangi untuk melangkah lebih jauh ke belakang dalam sejarah token terakhir. (Saya katakan token bukan arg, karena foo &meraih &sebagai token terakhir.) Anda dapat menggunakan argumen numerik (dengan escape-3 alt +. Misalnya).
Peter Cordes
lihat juga mkdir cd combo
Christopher Bottoms

Jawaban:

18

Alih-alih mendefinisikan fungsi, Anda bisa menggunakan variabel $_, yang diperluas ke argumen terakhir dari perintah sebelumnya dengan bash. Jadi gunakan:

cd "$_"

setelah mvperintah.

Anda juga dapat menggunakan ekspansi riwayat:

cd !:$

Jika Anda harus menggunakan fungsi:

follow () { cd "$_" ;}

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

NB: Jawaban ini ditargetkan ke format argumen baris perintah persis yang telah Anda gunakan saat kita berurusan dengan parameter posisi. Untuk format lain misalnya mv -t foo bar.txt, Anda harus memasukkan pemeriksaan khusus sebelumnya, pembungkus akan lebih sesuai.

heemayl
sumber
Perluasan riwayat Anda (cd!: $) Berfungsi dengan baik. Terima kasih. Namun, yang lain (cd "$ _") tidak: mv file.tex ~ / Downloads / cd "$ _" bash: cd: __bp_preexec_invoke_exec: Tidak ada file atau direktori seperti itu saya akan dengan senang hati menerima jawaban Anda sebagai sepenuhnya benar, dan Terima kasih.
Api
Saya selalu mengetik (agak terbuang) baik cd !$atau cd $(dirname !$). Tidak tahu tentang $_variabel!
Kalvin Lee
Sekarang apa yang terjadi jika saya lakukan mv -t ~/Documents file.texbukan mv file.tex ~/Documents? Intinya, saya tidak yakin ini dapat dipecahkan dalam kasus umum ... fungsi pembungkus di sekitar atau bahwa penambahan mvmungkin lebih baik ...
CVn
@ MichaelKjörling Tidak akan bekerja dengan mudah..contoh ini hanya untuk menutupi kasus OP, bukan tepi (atau semua) kasus ..
heemayl
Anda tidak membutuhkan usus besar; !$setara dengan !:$dan lebih cepat untuk mengetik.
Wildcard
14

Dengan keybindings bash standar, kombinasinya Alt. akan menyalin argumen terakhir dari baris perintah sebelumnya ke yang sekarang. Jadi, mengetik

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

akan menghasilkan

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

dan akan lebih sedikit mengetik daripada kata follow .

Untuk menambah kenyamanan, ulangi Alt. kombinasi akan menelusuri argumen terakhir dari semua baris perintah sebelumnya.

Tambahan: Nama perintah bash yang terkait dengan kombinasi tombol ini adalah yank-last-argatau insert-last-argument. Ini dapat ditemukan di halaman bash di bawah "Perintah untuk Memanipulasi Sejarah" atau di Manual Referensi Bash yang lebih lengkap .)

Dubu
sumber
1
Itu pintar. Terima kasih! Saya tidak tahu ini ada.
Api
@ Api Saya menambahkan referensi untuk perintah-perintah itu, sehingga Anda dapat menemukan banyak ikatan kunci yang lebih menarik (dan segera melupakannya lagi, seperti yang selalu saya lakukan).
Dubu
1
Anda juga dapat menggunakan <esc>itu .untuk mendapatkan hasil yang sama seperti <alt>+., ini berguna ketika Anda telah memetakan capslock untuk melarikan diri :)
gnur
1
@gnur vi (m) pengguna, saya kira. ;-)
Dubu
6

Anda hampir pasti mengalami masalah bahwa ekspansi tilde terjadi sebelum ekspansi parameter, yang dapat dijelaskan dengan contoh ringkas:

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

Ini bisa diatasi dengan eval . Bagaimanapun, Anda akan perlu eval, karena Anda menarik perintah dari sejarah dan mereka dapat berisi ekspansi sewenang-wenang, seperti:

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

(Ada masalah, seperti bahwa perluasan kembali nilai-nilai ini mungkin tidak lagi sesuai dengan ekspansi asli yang terjadi. Misalkan compute_folder_nameadalah fungsi yang menambah beberapa variabel global.)

Kaz
sumber
4
Anda tidak perlu eval. (Ever.) Tapi bagus melihat masalah urutan ekspansi. Jika Anda menyebutkan kelayakan ekspansi sejarah untuk digunakan di evalsini, ini akan menjadi jawaban terbaik menurut saya; tidak ada yang benar-benar menjelaskan mengapa solusi Poster Asli gagal berfungsi.
Wildcard