apakah mungkin mengubah direktori kerja shell induk secara terprogram?

8

Saya ingin menulis beberapa kode untuk memungkinkan saya beralih ke beberapa direktori yang biasanya saya kunjungi. Katakanlah program ini mycd, dan /a/very/long/path/namemerupakan direktori yang ingin saya kunjungi.

Jadi saya cukup mengetik mycd 2saja cd /a/very/long/path/name. Di sini saya menganggap mycdtahu 2mengacu pada itu /a/very/long/path/name. Mungkin juga ada mycd 1, mycd 3... dll

Masalahnya adalah saya harus menulis mycdsebagai skrip shell dan mengetik . mycd 2untuk melakukan hal yang diinginkan karena jika skrip hanya dieksekusi dalam skrip anak yang tidak mengubah apa pun tentang shell induk yang benar-benar saya pedulikan.

Pertanyaanku adalah:

  • dapatkah saya melakukannya tanpa menggunakan source? karena . mycdmenganggap mycdharus menjadi skrip shell dan ini mungkin juga memperkenalkan beberapa fungsi yang tidak saya inginkan.

  • dapatkah saya menerapkannya dalam beberapa bahasa pemrograman lain?

Jawa
sumber

Jawaban:

23

membuat mycdfungsi sehingga cdperintah dijalankan di shell Anda saat ini. Simpan di file ~ / .bashrc Anda.

function mycd {
    if (( $# == 0 )); then
        echo "usage: $FUNCNAME [1|2|3|...]"
        return
    fi
    case $1 in
        1) cd /tmp ;;
        2) cd /a/very/long/path/name ;;
        3) cd /some/where/else ;;
        *) echo "unknown parameter" ;;
    esac
}
glenn jackman
sumber
Terima kasih, belum memikirkan untuk menggunakan fungsi, dan ini hanya memungkinkan semuanya: Saya sekarang dapat membiarkan mycdlulus $@ke program apa pun yang saya suka.
Javran
Pastikan Anda mengutip "$@"sehingga setiap argumen yang mengandung spasi putih ditangani dengan benar.
glenn jackman
9

Anda tidak dapat mengubah direktori shell saat ini dari proses lain. Hanya proses itu sendiri yang dapat mengubah direktori saat ini. Ini juga berlaku untuk beberapa karakteristik lain seperti variabel lingkungan dan deskriptor file.

Sebenarnya mungkin untuk memengaruhi direktori proses saat ini dengan membuatnya menjalankan chdirpanggilan sistem melalui ptracepanggilan sistem, yang memungkinkan debuggers bekerja. Namun, jika proses mempertahankan beberapa struktur data internal yang harus konsisten dengan direktori aktual saat ini, program cenderung macet. Sebagai penutup, pendekatan ini tidak memiliki kesempatan untuk bekerja.

Anda perlu mengatur agar kode Anda dieksekusi oleh shell itu sendiri. Cara normal untuk melanjutkan adalah dengan membuatnya menjadi fungsi shell dan menyimpannya di ~/.bashrc. Jika ini tidak memungkinkan, misalnya karena itu kode yang ingin Anda distribusikan, tulis file sumber shell yang berisi definisi fungsi, dan beri tahu orang-orang agar shell interaktif mereka membaca file Anda dengan .perintah .

Gilles 'SANGAT berhenti menjadi jahat'
sumber
1
Sebenarnya ada kesempatan untuk membuatnya "berfungsi", tetapi itu tidak trivial, rawan kesalahan dan harus dihindari dengan cara apa pun. Untuk menunjukkan bahwa sebenarnya "mungkin", menganggap shell script ini di mana orang tua adalah Bash: ws=$1; gdb -p $(ps h -o ppid -p $$) -ex "call chdir(\"$wd\")" -ex "call set_working_directory(\"$wd\")" -ex detach -ex q -batch. Jalankan sebagai braindead-cd-parent /. Anda akan melihat bahwa pwdpengembalian /dan lsperilaku, dll. Tetapi prompt ( PS1) masih tidak berubah, mata orang terluka, dll. Jadi jangan lakukan ini bahkan jika itu mungkin.
Lekensteyn
1
@Lekensteyn Itulah ptracemetode yang saya sebutkan. Ini bekerja dengan baik pada program yang tidak terlalu peduli dengan direktori mereka saat ini. Dalam sebuah shell, banyak hal ( PWDvariabel, prompt, dll.) Akan menjadi salah, dan shell mungkin macet atau perilaku buruk.
Gilles 'SO- stop being evil'
5

Seperti yang Anda tunjukkan sendiri, skrip shell selalu dijalankan dalam subkulit, yang tidak dapat memengaruhi shell induknya.

Namun Anda dapat ...

  • gunakan alias:
    alias mycd2='cd /a/very/long/path/name'
  • minta script 1 Anda menampilkan perintah shell yang valid ...

    #!/bin/bash
    if [ "x$1" = "x2" ]
    then
        echo "cd /a/very/long/path/name"
    fi

    ... dan jalankan outputnya: $(mycd 2)

1: Anda mungkin ingin menggunakan casepernyataan daripada ifkondisi dalam contoh.

n.st
sumber
5
Sebuah alias bisa dilewati. Sebuah skrip adalah masalah yang sama yang sudah ia miliki. Pertanyaan ini meneriakkan fungsi shell.
Ricky Beam