Mengapa saya harus mengetikkan `. /` Sebelum menjalankan program di direktori saat ini?

92

Saat menjalankan program C a.out,, menggunakan terminal Ubuntu, mengapa saya selalu perlu mengetik ./sebelumnya a.out, bukan hanya menulis a.out? Apakah ada solusi untuk ini?

Prashant Chikhalkar
sumber

Jawaban:

119

Ketika Anda mengetik nama program seperti a.outsistem mencari file di PATH Anda. Di sistem saya, PATH diatur ke

/usr/lib/lightdm/lightdm:/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin:/usr/games:/usr/local/games

Milikmu mungkin serupa. Untuk memeriksa, masukkan echo $PATHterminal.

Sistem melihat melalui direktori ini dalam urutan yang diberikan dan jika tidak dapat menemukan program menghasilkan command not foundkesalahan.

Menjabarkan perintah dengan ./efektif mengatakan "lupakan tentang PATH, saya ingin Anda melihat hanya di direktori saat ini".

Demikian pula, Anda dapat memberi tahu sistem untuk melihat hanya di lokasi spesifik lain dengan menambahkan perintah dengan jalur relatif atau absolut seperti:

../artinya di direktori induk mis. ../hellocari hello di direktori induk.

./Debug/hello: "cari hellodi subdirektori Debug dari direktori saya saat ini."

atau /bin/ls: "cari lsdi direktori /bin"

Secara default, direktori saat ini tidak di jalur karena itu dianggap sebagai risiko keamanan. Lihat Mengapa. tidak di jalur secara default? pada Superuser untuk alasannya.

Dimungkinkan untuk menambahkan direktori saat ini ke PATH Anda, tetapi untuk alasan yang diberikan dalam pertanyaan yang ditautkan, saya tidak akan merekomendasikannya.

Warren Hill
sumber
25
Ini. +1 Jangan menambah .Anda PATH(seperti yang disarankan 2 jawaban lainnya) karena risiko keamanan yang disebutkan dalam jawaban ini.
Hari
8
Mungkin juga patut dicatat bahwa tidak ada yang istimewa di .sini, Anda dapat menggunakan path lengkap atau relatif ke executable misalnya /home/user/foo/a.outatau./build/a.out
tobyodavies
@tobyodavies; Sebenarnya .ini spesial karena ini berarti "direktori saya saat ini", jadi bisa berupa direktori apa pun yang ditemukan oleh pengguna dengan membaca dan mengeksekusi hak istimewa. Ini berpotensi lebih berbahaya daripada menambahkan jalur khusus yang sepenuhnya memenuhi syarat.
Warren Hill
@ WarrenHill ketika mempertimbangkan menambahkannya ke jalur Anda, ya itu sangat berbeda. Namun dalam hal sintaks bash, .tidak memiliki status khusus, itu hanya jalan yang bisa dimulai dengan /dan ./blahakan bekerja sama baiknya dengan catatau grepsebagai bash prompt.
tobyodavies
@tobyodavies: OK, saya sudah mengedit jawaban saya untuk memasukkan poin Anda.
Warren Hill
24

Alasannya sederhana.

Misalkan Anda memiliki perintah dengan nama yang sama dengan aplikasi di direktori saat ini. Kemudian menjalankan perintah di shell akan memanggil aplikasi Anda alih -alih perintah bawaan. Ini akan menjadi masalah keamanan jika tidak ada yang lain.

Dengan mengharuskan ./untuk digunakan di depan, shell tahu bahwa Anda ingin menjalankan aplikasi dengan nama yang diberikan dan bukan perintah bawaan dengan nama itu.

Nathan Osman
sumber
1
penjelasan Anda menyesatkan, ada perbedaan antara perintah bawaan di shell dan yang dapat dieksekusi yang dapat diakses melalui variabel PATH. Sebenarnya jawaban Anda semakin banyak saya baca rasanya lebih salah.
Ahmed Masud
16

./mengeksekusi file yang tidak ada di Anda $PATH, melainkan mengeksekusi file dalam direktori saat ini (atau yang lain melalui ./home/stefano/script.sh). Sekarang, PATH adalah variabel lingkungan yang berisi semua tempat di mana bash dapat mencari program yang dapat dieksekusi, tanpa memiliki path (absolut) penuh untuknya.

Pemisahan ini diperlukan untuk menghindari menjalankan file yang salah. Yaitu jika Anda memiliki file yang dipanggil lsdi direktori home Anda, itu tidak berada di PATH Anda akan mencegah bash dari membingungkannya dengan yang asli ls. Variabel PATH juga mendefinisikan urutan pencarian:

  • Ketika Anda menjalankan perintah, atau suatu program mencoba membuat execsyscall (metode khusus Kernel, bagaimana program dimulai), sistem mencari file dengan menelusuri setiap direktori di PATH Anda. Setelah program ditemukan, meskipun ada di banyak direktori, pencarian terputus dan yang pertama ditemukan dijalankan.

Untuk menjalankan file, Anda perlu mengatur bit yang dapat dieksekusi dalam izin:

  • Karena Anda sudah berada di baris perintah, Anda cukup mengetik chmod +x finename.

  • Atau Anda dapat mengatur izin dengan mengklik kanan file dan memilih Properties :

    teks alternatif

Anda sekarang dapat menyalin file ke salah satu direktori di PATH, untuk melihat mana yang ada di sana - dan mereka ditetapkan berdasarkan per pengguna - jenis echo $PATH.

stefano@3000-G530:~$ echo $PATH
/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin:/usr/games

Jika Anda membuat file yang dapat dieksekusi cat,, dan memindahkannya ke /usr/local/sbin, itu dijalankan bukannya yang tepat cat, yang berada di /bin. Anda dapat mengetahui di mana file Anda dengan menggunakan type catdan whereis cat.

Stefano Palazzo
sumber
2
Satu hal yang perlu diperhatikan: pertanyaannya tampaknya menunjukkan bahwa ia telah menyusun dan menautkan sesuatu dengan gcc, yang secara otomatis mengatur bit eksekusi.
Nathan Osman
12

Mengapa Anda perlu mengetik ./sebelum menjalankan program?

Di terminal, setiap kali Anda mengetik nama aplikasi, katakanlah gedit, terminal akan mencari di beberapa direktori (yang ditentukan sebelumnya) yang berisi aplikasi (binari aplikasi). Nama-nama direktori ini terkandung dalam variabel yang disebut PATH. Anda dapat melihat apa yang ada di variabel ini dengan mengeksekusi echo $PATH. Lihat direktori yang dipisahkan oleh :? Mereka adalah direktori yang terminal akan dicari, jika Anda hanya mengetik gedit, nautilusatau a.out. Seperti yang Anda lihat, jalur a.outprogram Anda tidak ada. Ketika Anda melakukannya ./a.out, Anda memberi tahu terminal "lihat di direktori saat ini, dan jalankan a.out, dan jangan masuk PATH.

Solusi 1

Jika Anda tidak ingin mengetik ./setiap waktu, Anda harus menambahkan a.outdirektori $PATH. Dalam instruksi berikut, saya akan menganggap bahwa jalan menuju a.outadalah /path/to/programs/, tetapi Anda harus mengubahnya ke jalan Anda yang sebenarnya.

  1. Cukup tambahkan baris berikut ke akhir file ~/.pam_environment:

    PATH DEFAULT=${PATH}:/path/to/programs

    Sumber: Variabel lingkungan persisten

  2. Logout dan log in kembali. Sekarang Anda dapat berjalan a.outtanpa ./dari direktori mana pun.

Jika Anda memiliki program lain di direktori lain, Anda bisa menambahkannya ke baris di atas. Namun, saya menyarankan untuk memiliki satu direktori bernama "myPrograms" misalnya, dan letakkan semua program Anda di bawahnya.

Solusi 2

Catatan: ubah userNamenama pengguna Ubuntu Anda yang sebenarnya.

Bagaimana jika Anda memiliki program lain yang ingin Anda jalankan? Dan mereka semua ada di folder yang berbeda? Nah, solusi "lebih terorganisir" adalah membuat folder yang disebut di binbawah direktori Beranda Anda, dan menambahkan tautan simbolis (pintasan) di bawah folder itu. Begini caranya:

  1. mkdir /home/userName/bin

    • Ini akan membuat folder di binbawah direktori Beranda Anda.
  2. ln -s /path/to/programs/a.out /home/userName/bin

    • Ini akan membuat "tautan simbolik" (pada dasarnya, pintasan) dari a.outprogram Anda di bawah bin.
  3. Logout dan log in kembali. Sekarang Anda dapat berjalan a.outtanpa ./dari direktori mana pun.

Sekarang, setiap kali Anda memiliki program lain di tempat lain, katakanlah program b.indi Desktop Anda, yang perlu Anda lakukan adalah:, ln -s /home/userName/Desktop/b.in /home/userName/bindan Anda kemudian dapat menjalankannya tanpa ./.

Catatan: terima kasih atas komentar @ Joe , ketika Anda melakukan backup, tautan simbolik harus ditangani secara khusus. Secara default, rsynctidak memprosesnya sama sekali, jadi ketika Anda mengembalikan, mereka tidak ada di sana.

Alaa Ali
sumber
1
Ini adalah trik yang berguna jika digunakan dengan hemat. Menggunakannya banyak membuat sistem Anda melakukan hal-hal yang orang lain tidak harapkan. Juga, ketika Anda melakukan pencadangan, symlink harus ditangani secara khusus. Secara default , rsync tidak memprosesnya sama sekali, jadi ketika Anda mengembalikannya, rsync tidak ada.
Joe
1

Seperti George tunjukkan dalam jawabannya, ini membantu Anda mencatat bahwa Anda mengeksekusi file di direktori kerja saat ini ( pwd).

Saya ingat menanyakan pertanyaan ini kepada senior saya sejak lama, dia berkata saya harus menambahkan .ke jalur saya sehingga ketika saya a.outmelihatnya di direktori saat ini dan mengeksekusi itu. Dalam hal ini saya tidak perlu melakukan ./a.out.

Tetapi, secara pribadi, saya akan merekomendasikan untuk tidak melakukannya. Itu tidak pernah terjadi pada saya, tetapi jika Anda berada di direktori jaringan alien atau sesuatu, dan file eksekusi berbahaya yang disebut lsada di sana, maka memiliki .di jalur Anda adalah ide yang sangat buruk. Bukan berarti Anda akan mengalami masalah ini sangat sering, hanya mengatakan.

Shrikant Sharat
sumber
ok, Stefano mengadopsi jawabannya untuk memuat info ini :)
Shrikant Sharat
3
Saya sepenuhnya setuju dengan tidak menambahkan .untuk $PATH. Ide yang sangat berbahaya.
Nathan Osman
1

Selain jawaban lain, di sini bagian penting dari man bashyang menjelaskan dengan baik:

EKSEKUSI PERINTAH
       Setelah perintah telah dipecah menjadi kata-kata, jika itu menghasilkan sederhana
       perintah dan daftar argumen opsional, tindakan berikut adalah
       diambil.

       Jika nama perintah tidak mengandung garis miring, shell mencoba mencari
       saya t. Jika ada fungsi shell dengan nama itu, fungsi itu adalah
       dipanggil seperti yang dijelaskan di atas dalam FUNGSI. Jika nama tidak cocok a
       fungsi, shell mencarinya dalam daftar builtins shell. Jika
       kecocokan ditemukan, bahwa builtin dipanggil.

       Jika namanya bukan fungsi shell atau builtin, dan tidak mengandung
       slash, bash mencari setiap elemen PATH untuk direktori con-
       menyimpan file yang dapat dieksekusi dengan nama itu.
mook765
sumber
0

A './' masuk akal ketika Anda menjalankan program yang dikenal untuk Anda dan spesifik, misalnya program Anda sendiri. Program ini harus ada di direktori Anda saat ini. A './' tidak masuk akal ketika Anda menjalankan perintah standar yang ada di suatu tempat di $ PATH. Perintah "yang menjalankan perintah" memberitahu Anda di mana perintah untuk dijalankan berada di $ PATH.

pengguna7346
sumber
0
$ gcc hello.c -o /path/to/someplace/hello

akan menghasilkan executable di beberapa lokasi. Jika lokasi itu di jalur Anda, Anda akan dapat menjalankan file. Anda dapat membuat skrip ini jika Anda ingin membuat label untuk tindakan "kompilasi kode sumber ini menggunakan gcc dan letakkan sebuah executable di beberapa lokasi yang ada di jalur Anda"

Saya sarankan Anda membuat direktori baru yang disebut "testbin" atau semacam itu dan letakkan di path Anda untuk menjaga direktori path yang ada bersih.

Jon Kiparsky
sumber
0

./menghilangkan pencarian jalur yang tidak perlu. ./memaksa untuk mencari di direktori saat ini saja. Jika kita tidak memberikan ./maka akan mencari berbagai jalan mengatur ke dalam sistem seperti /usr/bin, /usr/sbin/, dll

pengguna175959
sumber
0

"./" berarti Anda ingin mengeksekusi file di direktori saat ini dengan cara pintas untuk mengetik seluruh path misalnya:

[root@server ~]#/path/to/file/file.pl

sama dengan:

[root@server file]#./file.pl

dalam contoh sebelumnya Anda pergi melalui direktori dan direktori-supirnya ke lokasi file dan menggunakan "./" untuk menjalankan file di direktori saat ini.

yang sebelumnya " [root @ server ~] # / path / ke / file / file.pl " juga akan mengeksekusi file jika Anda malas untuk "cd" jalan ke lokasi file.

Khaled Moustafa
sumber
-4

Ini sangat sederhana dan memiliki banyak kegunaan.

  1. Ketika beberapa versi aplikasi yang sama diinstal, itu akan tersedia di jalur yang berbeda tetapi tautan lunak ke biner Anda dapat dibuat di /usr/bin. Sebagai contoh, Python 2.7, Python 2.6 diinstal tetapi / usr / bin / python -> python2.7 / usr / local / bin / python -> python2.6

Jika Anda berada di jalur /usr/local/bindan mengeksekusi Python akan selalu mengeksekusi Python 2.7. Menentukan .akan membuat folder saat ini dapat dieksekusi.

  1. .- selalu mewakili eksekusi dari direktori saat ini. Dan ..selalu berarti dijalankan dari direktori sebelumnya.
Ramjee Anna
sumber