Mengapa "cd" tidak berfungsi di skrip shell?

43

Saya hanya ingin menulis skrip yang mengubah direktori saya .

Saya menaruh perintah di bawah ini dalam file /home/alex/pathABC

#!/bin/sh
cd /home/alex/Documents/A/B/C
echo HelloWorld

Saya lakukan chmod +x pathABC.

Di terminal, sementara di /home/alex, saya jalankan ./pathABC, tetapi hasilnya adil HelloWorlddan direktori saat ini tidak berubah.

Jadi apa yang salah?

Mohammad Reza Rezwani
sumber

Jawaban:

74

Seperti yang telah dijelaskan orang lain, direktori diubah dalam proses anak skrip Anda, bukan dalam proses terminal dari mana skrip dipanggil. Setelah proses anak meninggal, Anda kembali ke terminal yang tersisa di tempatnya.

Beberapa alternatif:

1. Tautan simbolik

Letakkan symlink di rumah Anda ke jalur panjang yang ingin Anda akses dengan mudah

$ ln -s /home/alex/Documents/A/B/C ~/pathABC

lalu akses direktori dengan:

$ cd ~/pathABC

2. Alias

Masukkan alias di ~ / .bashrc Anda:

alias pathABC="cd /home/alex/Documents/A/B/C"

(dari sini )

3. Fungsi

Buat fungsi yang mengubah direktori, fungsi berjalan dalam proses terminal Anda dan kemudian dapat mengubah direktori-nya.

(dari sini )

4. Hindari berlari saat kecil

Sumber skrip Anda alih-alih menjalankannya. Sourcing (dilakukan oleh .atau source) menyebabkan skrip dieksekusi di shell yang sama dan bukannya dijalankan di subkulitnya sendiri.

$ . ./pathABC

(dari sini dan sini )

5. vars yang dapat di-cd

Setel cdable_varsopsi di Anda ~/.bashrcdan buat variabel lingkungan ke direktori:

shopt -s cdable_vars
export pathABC="/home/alex/Documents/A/B/C"

Maka Anda bisa menggunakannya cd pathABC

(dari sini )

Gauthier
sumber
15
Sekarang saya mengerti penggunaan source! Saya selalu bertanya-tanya mengapa saya lakukan source .bashrcdan tidakbash .bashrc
hytromo
Opsi 3 bekerja sangat baik. Saya baru saja mendefinisikan fungsi go_to_wherever () {cd my / directory} di awal skrip saya. Sebut saja sebelum menjalankan operasi di direktori itu.
i2097i
> 5. vars yang dapat di-cd - bukan cd $pathABC?
loxaxs
7

Saat Anda menjalankan skrip di terminal, proses anak berjalan. Dalam program anak ini, skrip Anda akan berubah ke direktori apa pun yang ditentukan. Tetapi dalam proses induk yaitu di mana Anda menjalankan skrip masih di jalur lama. ATAU sederhananya kita dapat mengatakan:

The scope of cd command is only for child process not parent

Tingrammer
sumber
2
Menambahkan ke ini, @alex untuk mencapai efek yang Anda cari, jalankan skrip dalam proses induk dengan sumbernya: salah satu . pathABCatau source pathABC.
zwets
4

Anda membuat kesalahan berpikir. Sementara shell saat ini tetap berada di direktori yang sama, skrip telah pindah ke direktori baru.

Anda bisa melihatnya dengan membuat skrip lain di direktori baru , dan menjalankannya dari skrip Anda, setelah itu mengubah direktori:

#!/bin/sh
cd /home/alex/Documents/A/B/C && ./another_script.sh # (if it is executable)

Script kedua akan dijalankan dari direktori baru.

HelloWorld 

hanyalah output dari skrip.

Yakub Vlijm
sumber
3
HelloWorld tidak "dikembalikan" ke shell induk, itu output ke output standar
Mog
Mungkin lebih jelas jika Anda hanya menjalankan pwddi direktori baru, daripada menambahkan skrip baru ke dalam situasi.
wjandrea
0

Karena hello world hanyalah pernyataan jejak, mari kita coba ini:

Buat file skrip bash yang cd.shberisi:

#!/bin/bash
echo "/home/mike/Documents/A/B/C"
  • The .shekstensi konvensi yang lebih tua memberikan bash script nama file ekstensi. Ini murni kosmetik dan biasanya tidak perlu. Namun dalam hal ini penting untuk membedakan dari cdperintah inti .

Tandai file skrip bash yang dapat dieksekusi menggunakan:

chmod a+x cd.sh

Sekarang jalankan file:

$ cd $(./cd.sh)
bash: cd: /home/alex/Documents/A/B/C: No such file or directory
  • cd kita semua tahu.
  • $(...) mengeksekusi perintah di dalam tanda kurung dan mengembalikan output.
  • Jika cd.shberada di jalur Anda, Anda tidak perlu menentukan di mana itu. Kami awali dengan ./untuk menentukan perintah di direktori saat ini.
  • The echooutput dari cd.shnaskah dikirim kembali ke orangtua melalui $(...). Induk (prompt shell kami) menggunakan output ini dan meneruskannya ke cdperintah Linux .

Seperti yang disebutkan orang lain, proses anak tidak dapat mengubah direktori induk. Ini adalah salah satu cara anak dapat memberi tahu orang tua ke mana harus pergi setelah proses berakhir.

WinEunuuchs2Unix
sumber
@wjandrea Itulah yang Anda dapatkan untuk pengkodean di telepon! Baru pulang, aku akan memperbaikinya. Terima kasih. Um baru saja diperiksa dan berfungsi dengan baik. Mungkin ini 14.04versi Anda yang saya baca sekitar satu jam yang lalu?
WinEunuuchs2Unix
Nah, Anda benar-benar mengubah skripnya. Sebelumnya itu hanya satu perintah:, cd /home/mike/Documents/A/B/Cyang tidak menghasilkan output apa pun. Sekarang echo "/home/mike/Documents/A/B/C", yang menghasilkan output.
wjandrea
@wjandrea Benar, saya juga benar-benar mengubah cara memanggil skrip juga. Alih-alih sederhana ./cd.shitu sekarang cd $(./cd.sh)tapi itu mencapai tujuan anak mengubah direktori saat ini orang tua. Ya itu tidak konvensional tapi itu cara lain untuk melakukannya yang saya harap orang-orang temukan menarik.
WinEunuuchs2Unix