Saya telah membuat program C sederhana seperti:
int main(int argc, char *argv[]) {
if (argc != 5) {
fputs("Not enough arguments!\n", stderr);
exit(EXIT_FAILURE);
}
Dan PATH saya sudah dimodifikasi di etc / bash.bashrc seperti:
PATH=.:$PATH
Saya telah menyimpan program ini sebagai set.c dan sedang mengompilasinya
gcc -o set set.c
dalam folder
~/Programming/so
Namun, ketika saya menelepon
set 2 3
tidak ada yang terjadi. Tidak ada teks yang muncul.
Panggilan
./set 2 3
memberikan hasil yang diharapkan
Saya tidak pernah punya masalah dengan PATH sebelum dan
which set
kembali ./set
. Jadi sepertinya PATH adalah yang benar. Apa yang terjadi
shell
path
shell-builtin
Ganea Dan Andrei
sumber
sumber
test
karena alasan yang sama;test
adalah built-in shell juga.test
tampaknya masuk akal. Tentu saja pada saat Anda memasukkannya ke dalam Anda,PATH
Anda benar-benar harus datang dengan nama yang berbeda. Dan sampai Anda memasukkan programPATH
ke dalamnya, Anda tetap harus memintanya./test
. Jadi boleh saja menggunakan namatest
untuk program selama itu adalah tes cepat yang ingin Anda hapus sebelum akhir hari.foo
.ls
maka setiap kali Anda pergi untuk melihat apakah ada itu akan berjalan (tetapi hanya jika Anda memodifikasi jalur Anda seperti yang Anda lakukan dalam pertanyaan).Jawaban:
Alih-alih menggunakan
which
, yang tidak berfungsi saat Anda paling membutuhkannya , gunakantype
untuk menentukan apa yang akan berjalan saat Anda mengetik perintah:Shell selalu mencari bawaan sebelum mencari
$PATH
, jadi pengaturan$PATH
tidak membantu di sini.Akan lebih baik untuk mengubah nama executable Anda menjadi sesuatu yang lain, tetapi jika tugas Anda mengharuskan program untuk dinamai
set
, Anda dapat menggunakan fungsi shell:(Itu berfungsi
bash
, tetapi cangkang lain sepertiksh
tidak memungkinkan. Lihat jawaban mikeserv untuk solusi yang lebih portabel.)Sekarang mengetik
set
akan menjalankan fungsi bernama "set", yang dijalankan./set
. GNUbash
mencari fungsi sebelum mencari builtin, dan mencari builtin sebelum mencari$PATH
. Bagian bernama "PERINTAH EKSEKUSI" di halaman bash man memberikan informasi lebih lanjut tentang ini.Lihat juga dokumentasi pada
builtin
dancommand
:help builtin
danhelp command
.sumber
type
lebihwhich
, tetapi jangan memberikan alasan mengapa. ( Saya tahu mengapa , tetapi seseorang yang membutuhkan rekomendasi tidak akan melakukannya.)type
sebagai gantiwhich
, jangan beri nama program Anda "set", dan sadari bahwa itufunction set { ./set; }
adalah peretasan jelek yang mungkin harus Anda hindari.set
adalah builtin di bash (dan mungkin sebagian besar shell lainnya). Ini berarti bahwa bash bahkan tidak akan mencari jalan ketika mencari fungsi.Sebagai komentar sampingan, saya akan sangat menyarankan agar tidak menambah
.
jalan demi alasan keamanan. Bayangkan misalnyacd
ing dari/tmp
setelah pengguna lain menambahkan file eksekusi/tmp/cd
.sumber
cd
adalah shell bawaan, jadi contohnya tidak akan bekerja karena alasan yang sama denganset
../foo
untuk menjalankan program adalah profesional; itu menunjukkan bahwa Anda mengerti mengapa.
tidak harus dalam $ PATH. Gurumu salah, dan kamu bisa memberitahunya aku bilang begitu.set
bukan hanya builtin, itu adalah builtin khusus POSIX . Ada beberapa perintah builtin yang ditentukan oleh standar untuk ditemukan dalam pencarian perintah sebelum hal lain -$PATH
tidak dicari, nama fungsi tidak dicari, dan lain-lain. Kebanyakan builtin yang tidak spesial sebenarnya diperlukan oleh standar POSIX untuk menjadi ditemukan di shell Anda$PATH
sebelum akan menjalankan salah satu prosedur builtin sendiri. Hal ini berlaku dariecho
dan kebanyakan orang lain (meskipun apakah standar dihormati dalam hal ini telah menjadi masalah pertentangan di kelompok terbuka milis di masa lalu) , tapi tidak dariset
,trap
,break
,return
,continue
,.
,:
,times
,eval
,exit
,export
,readonly
,unset
, Atauexec
.Semua ini adalah nama yang dilindungi dari shell, dan mereka memiliki atribut khusus selain urutan preferensi mereka untuk pencarian perintah juga. Misalnya, Anda tidak bisa mendefinisikan fungsi shell dengan nama-nama itu di shell yang sesuai standar. Ini adalah hal yang baik - ini memungkinkan orang untuk menulis skrip portabel dengan aman . Ini adalah perintah dasar dari mana penulis naskah berpengalaman dapat membangun pijakan yang aman dan dapat diandalkan di lingkungannya. Menyerang namespace ini tidak disarankan.
Namun, jika Anda ingin menyerbunya, Anda dapat melakukannya dengan nyaman
alias
. Urutan ekspansi shell memungkinkan ini diselesaikan. Karenaalias
diperluas ketika perintah sedang dibaca, apa pun yang Anda gantiset
namanya dengan definisi Anda akan diperluas dengan benar, mungkin saja itu tidak boleh diperluas ke salah satu dari nama-nama itu.Jadi Anda bisa melakukan:
... yang akan bekerja dengan baik.
sumber
Masalahnya adalah
set
shell builtin dan solusi terbaiknya adalah menggunakan nama yang berbeda untuk program yang dapat dieksekusi.Kebetulan, minggu lalu, saya mengajukan pertanyaan tentang cara menjalankan perintah sistem alih-alih shell builtin dengan nama yang sama dan solusi yang saya terima adalah menjalankan perintah melalui
env
:Untuk kasus khusus ini, di mana Anda sudah tahu bahwa perintah yang ingin Anda gunakan terletak di direktori Anda saat ini, akan lebih baik untuk langsung menjalankan executable dengan memasukkan path-nya (menggunakan
.
untuk mewakili direktori kerja saat ini):Kedua solusi di atas adalah agnostik shell, yaitu mereka akan bekerja terlepas dari shell yang Anda gunakan.
Saran seperti menggunakan
command
builtin tidak akan berfungsi di Bash: ini hanya mencegah fungsi shell dijalankan. Meskipun tidak terdokumentasi, saya juga memperhatikan bahwa menggunakancommand
juga menekan kata kunci shell . Namun, itu tidak akan melakukan hal yang sama untuk shell builtin sepertiset
. Seperti yang saya pahami,command
dapat bekerja dengan shell lain seperti zsh.Juga, trik seperti
\set
atau"set"
atau'set'
tidak bekerja untuk builtin Bash - meskipun mereka berguna untuk menjalankan file executable bukan alias atau shell kata kunci .Catatan: Jawaban ini awalnya dimulai sebagai komentar atas jawaban Eric (diterima) tetapi tumbuh terlalu besar untuk dicocokkan dengan komentar. Jawaban lain yang merekomendasikan penggunaan
type
dan tidak menambah.
PATH adalah jawaban yang bagus.sumber