Jawaban singkat
Dalam pertanyaan Anda, perintah kedua tidak menggunakan .
shell builtin atau source
builtin. Alih-alih, Anda sebenarnya menjalankan skrip dalam shell yang terpisah, dengan menjalankannya dengan nama seperti yang Anda lakukan dengan file yang dapat dieksekusi lainnya. Ini memberikannya seperangkat variabel terpisah (meskipun jika Anda mengekspor variabel dalam shell induknya, itu akan menjadi variabel lingkungan untuk setiap proses anak , dan karenanya akan dimasukkan dalam variabel shell anak ). Jika Anda mengubah /
ke ruang, maka itu akan menjalankannya dengan .
built-in, yang setara dengan source
.
Penjelasan Lebih Lanjut
Ini adalah sintaks dari source
built-in shell, yang mengeksekusi isi skrip di shell saat ini (dan dengan demikian dengan variabel shell saat ini):
source testenv.sh
Ini adalah sintaks dari .
built-in, yang melakukan hal yang sama seperti source
:
. testenv.sh
Namun, sintaks ini menjalankan skrip sebagai file yang dapat dieksekusi, meluncurkan shell baru untuk menjalankannya:
./testenv.sh
Itu tidak menggunakan .
built-in. Sebaliknya, .
adalah bagian dari jalur ke file yang Anda jalankan. Secara umum, Anda dapat menjalankan file yang dapat dieksekusi di shell dengan menjalankannya dengan nama yang mengandung setidaknya satu /
karakter. Untuk menjalankan file di direktori saat ini, mendahului dengan ./
demikian merupakan cara termudah. Kecuali direktori saat ini ada di Anda PATH
, Anda tidak dapat menjalankan skrip dengan perintah testenv.sh
. Ini untuk mencegah orang dari mengeksekusi file secara tidak sengaja di direktori saat ini ketika mereka bermaksud untuk mengeksekusi perintah sistem atau file lain yang ada di beberapa direktori yang tercantum dalam PATH
variabel lingkungan.
Karena menjalankan file dengan nama (bukan dengan source
atau .
) menjalankannya di shell baru, itu akan memiliki set variabel shell sendiri. Shell baru memang mewarisi variabel lingkungan dari proses pemanggilan (yang dalam hal ini adalah shell interaktif Anda) dan variabel lingkungan tersebut menjadi variabel shell di shell baru. Namun, untuk variabel shell yang akan diteruskan ke shell baru, salah satu dari berikut ini harus terjadi:
Variabel shell telah diekspor, menyebabkannya menjadi variabel lingkungan. Gunakan export
shell built-in untuk ini. Dalam contoh Anda, Anda dapat menggunakan export MY_VAR=12345
untuk mengatur dan mengekspor variabel dalam satu langkah, atau jika sudah diatur, Anda dapat menggunakannya export MY_VAR
.
Variabel shell secara eksplisit diatur dan diteruskan untuk perintah yang Anda jalankan, menjadikannya variabel lingkungan selama durasi perintah dijalankan. Ini biasanya mencapai bahwa:
MY_VAR=12345 ./testenv.sh
Jika MY_VAR
variabel shell yang belum diekspor, Anda bahkan dapat menjalankan testenv.sh
dengan MY_VAR
meneruskan sebagai variabel lingkungan dengan mengaturnya sendiri :
MY_VAR="$MY_VAR" ./testenv.sh
./
Sintaks untuk Skrip Membutuhkan Baris Hashbang untuk Bekerja (dengan Benar)
Ngomong-ngomong, perlu diketahui bahwa, ketika Anda menjalankan executable dengan nama seperti di atas (dan tidak dengan .
atau source
built-in shell), program shell apa yang digunakan untuk menjalankannya biasanya tidak ditentukan oleh shell yang Anda jalankan dari mana . Sebagai gantinya:
Untuk file biner, kernel dapat dikonfigurasi untuk menjalankan file jenis tertentu. Ini memeriksa dua byte pertama dari file untuk "angka ajaib" yang menunjukkan jenis biner yang dapat dieksekusi. Ini adalah bagaimana binari yang dapat dieksekusi dapat dijalankan.
Ini, tentu saja, sangat penting, karena skrip tidak dapat berjalan tanpa shell atau penerjemah lain, yang merupakan biner yang dapat dieksekusi! Plus, banyak perintah dan aplikasi yang disusun binari daripada skrip.
( #!
adalah representasi teks dari "angka ajaib" yang menunjukkan teks yang dapat dieksekusi.)
Untuk file yang seharusnya dijalankan di shell atau bahasa yang diterjemahkan lainnya, baris pertama terlihat seperti:
#!/bin/sh
/bin/sh
dapat diganti dengan shell atau interpreter lain apa pun yang dimaksudkan untuk menjalankan program. Misalnya, program Python mungkin dimulai dengan baris:
#!/usr/bin/python
Garis-garis ini disebut hashbang, shebang, dan sejumlah nama serupa lainnya. Lihat entri FOLDOC ini , artikel Wikipedia ini dan Apakah #! / Bin / sh dibaca oleh penerjemah? untuk informasi lebih lanjut.
Jika file teks ditandai dapat dieksekusi dan Anda menjalankannya dari shell Anda (seperti ./filename
) tetapi tidak dimulai dengan #!
, kernel gagal untuk mengeksekusinya. Namun, melihat bahwa ini telah terjadi, shell Anda akan mencoba menjalankannya dengan memberikan namanya ke beberapa shell. Ada beberapa persyaratan yang ditempatkan pada shell apa itu ( "shell harus menjalankan perintah yang setara dengan meminta shell dipanggil ..." ). Dalam praktiknya , beberapa shell - termasuk bash
* - menjalankan instance lain dari dirinya, sementara yang lain menggunakannya/bin/sh
. Saya sangat menyarankan Anda menghindari ini dan menggunakan baris hashbang sebagai gantinya (atau menjalankan skrip dengan meneruskannya ke penerjemah yang diinginkan, misalnya, bash filename
).
* Manual GNU Bash , 3.7.2 Pencarian dan Eksekusi Perintah : "Jika eksekusi ini gagal karena file tidak dalam format yang dapat dieksekusi, dan file tersebut bukan direktori, itu diasumsikan sebagai skrip shell dan shell mengeksekusi seperti yang dijelaskan dalam Script Shell . "
source
adalah bahwa fungsi menjadi tersedia dari bash tanpa perlu memuat atau meluncurkan lagi. Contoh#!/bin/bash function olakease {echo olakease;}
. Setelah Anda memuatnya,source file.sh
Anda dapat langsung meneleponolakease
dari bash. Saya sangat suka itu. Sumber mengeksekusi kemudian memuat banyak hal, titik.
hanya untuk eksekusi dan sesuatu seperti penggunaanbash file.sh
.
memiliki perilaku ini juga:. file.sh
dansource file.sh
melakukan hal yang persis sama, termasuk mempertahankan fungsi yang didefinisikan dalamfile.sh
. (Mungkin Anda berpikir./file.sh
, yang berbeda. Tetapi itu tidak menggunakan.
builtin; sebaliknya,.
adalah bagian dari jalan.)Ya, Anda melewatkan sesuatu.
Saya pikir Anda membingungkan '.' itu berarti direktori saat ini, seperti pada
./testenv.sh
dan '.' itu berartisource
(yang merupakan perintah bawaan). Jadi dalam kasus ketika '.' berartisource
itu akan terjadi. ./testenv.sh
. Masuk akal?Jadi coba ini:
sumber
./
mengatakan itu persis di mana file itu, tanpa itu, bash akan melihat melalui PATH pertama, kemudian mencoba dir saat ini jika tidak menemukannya. Jika bash berjalan dalam mode POSIX, dan Anda tidak memberikan path ke file (seperti./
), itu hanya akan mencari di PATH, dan gagal menemukan file jika direktori saat ini tidak di PATH.source
(dan.
) sebenarnya akan memeriksa $ PATH terlebih dahulu, meskipun mereka tidak benar-benar menjalankan skrip seperti biasanya. Komentar (mantan) saya salah.