Neden bash'de çalıştırmak için çalıştırılabilir dosyadan veya komut dosyası adından önce ./ (dot-slash) gerekiyor?


288

Bash komut dosyalarını çalıştırırken ./, başlangıçta yazmak zorundayım :

$ ./manage.py syncdb

Eğer yapmazsam bir hata mesajı alıyorum:

$ manage.py syncdb
-bash: manage.py: command not found

Bunun nedeni nedir? .Geçerli klasör için bir takma ad olduğunu düşündüm ve bu nedenle bu iki çağrı eşdeğer olmalıdır.

Ayrıca ./, uygulamaları çalıştırırken neden ihtiyacım olmadığını anlamıyorum , örneğin:

user:/home/user$ cd /usr/bin
user:/usr/bin$ git

(olmadan çalışır ./)


4
Bu, şimdiye kadar karşılaştığım konuyla ilgili en iyi belge: linfo.org/dot_slash.html
odigity

Yanıtlar:


307

Çünkü Unix'te genellikle geçerli dizin içinde değildir $PATH.

Bir komut yazdığınızda, kabuk PATHdeğişken tarafından belirtildiği gibi bir dizin listesi arar . Geçerli dizin bu listede değil.

Bu listede geçerli dizinin bulunmamasının nedeni güvenliktir.

Kök olduğunuzu ve slbunun yerine başka bir kullanıcının dizinine ve türüne girdiğinizi varsayalım ls. Geçerli dizin varsa, PATHkabuk slo dizindeki programı yürütmeye çalışır (başka bir slprogram olmadığından ). Bu slprogram kötü amaçlı olabilir.

Bu çalışır ./çünkü POSIX belirten bir içerirler bir komut adı olduğu /bir arama bastırmak, doğrudan dosya adı olarak kullanılacaktır $PATH. Aynı etki için tam yol kullanmış olabilirsiniz, ancak ./daha kısa ve yazılması daha kolaydır.

DÜZENLE

Bu slkısım sadece bir örnekti. İçindeki dizinler PATHsırayla aranır ve bir eşleşme yapıldığında o program yürütülür. Bu nedenle, nasıl PATHgöründüğüne bağlı olarak , normal bir komut yazmak, programı geçerli dizinde çalıştırmak için yeterli olabilir veya olmayabilir.


47
Hiçbir şeyi yanlış yazmanıza gerek yok. Kullanıcı, lsiçinde yürütülebilir bir dosya bulunan kötü amaçlı bir paket indirmiş olabilir .
Juliano

13
Herkesin bunun sadece Windows'da değil Unix'te olduğunu söyleyen bir not, bu Powershell'de de aynı - .\my.batyürütmek için vb.
Yapmanız gerekiyor

1
@gaearon ergh, dedim ki "bu bir takma ad değil", "kesinlikle bir takma ad" olmalıydı.
Charles Duffy

4
Bu çok yardımcı oldu. 20+ yıl önce DOS ile biraz çalıştığımda, CMD'nin mevcut dizini, SONRA YOLU kontrol edeceğini düşünüyorum, bu yüzden Linux'un davranışı beklediğim gibi değildi, ama çok mantıklı.
TecBrat

2
@cnicutar: İlginç bir şekilde bugün slvarsayılan olarak mevcut olmasa da buharlı lokomotif adı verilen bir komut olduğunu buldum ;-)
blackSmith

51

Bash komut satırını yorumlarken, ortam değişkeninde açıklanan konumlardaki komutları arar $PATH. Görmek için şunu yazın:

echo $PATH

İki nokta üst üste ile ayrılmış bazı yollarınız olacaktır. Göreceğiniz gibi mevcut yol .genellikle içinde değildir $PATH. Dolayısıyla, Bash geçerli dizinde ise komutunuzu bulamaz. Aşağıdakilere sahip olarak değiştirebilirsiniz:

PATH=$PATH:.

Bu satır, $PATHaşağıdakileri yapabilmeniz için geçerli dizini ekler :

manage.py syncdb

Güvenlik sorunu olduğu için önerilmez, ayrıca içinde .bulunduğunuz dizine bağlı olarak garip davranışlar yaşayabilirsiniz :)

Önlemek:

PATH=.:$PATH

Bazı standart komutları “maskeleyebildiğiniz” ve güvenlik ihlaline kapıyı açabildiğiniz için :)

Sadece iki sentim.


42

Kabuğunuz $PATH, komut dosyanızı bulmak için ortam değişkenine baktığında, ana dizininizdeyken komut dosyanız bulunmaz .

./'Belirtilen tüm dizinleri benim komut dosyası için geçerli dizinde göz ziyade seyir diyor $PATH'.


5

'.' esas olarak çalıştırılabilir bash betiğine "tam yol" veriyorsunuz, bu nedenle kabuğunuzun PATH değişkeninizi kontrol etmesi gerekmez. '.' Kabuğunuz PATH değişkeninize bakar ( echo $PATHyazdığınız komutun PATH'nizdeki klasörlerden herhangi birinde yaşayıp yaşamadığını görmek için koşarak görebilirsiniz. Eğer değilse (manage.py ile olduğu gibi) dosyayı bulamıyor iyi burada makul açıklanmıştır PATH, mevcut dizin eklemek için kötü uygulama olarak kabul edilir. http://www.faqs.org/faqs/unix-faq/faq/part2/section- 13.html


2

* Nix'de, Windows'tan farklı olarak, geçerli dizin genellikle $PATHdeğişkeninizde değildir . Dolayısıyla, komutlar yürütülürken geçerli dizin aranmaz. Buna gerek yok ./bu uygulamalar nedeniyle uygulamalarını çalıştırmak için vardır $ PATH içinde; büyük olasılıkla /binveya /usr/bin.


1

Bu sorunun zaten bazı harika cevapları var, ancak yürütülebilir dosya PATH üzerindeyse ve çalıştırdığınızda çok farklı çıktılar elde etmek istedim.

./executable

koşarsan aldığınlara

executable

(diyelim ki diğeriyle değil diğeriyle hata iletileri alıyorsunuz), sorun makinenizde çalıştırılabilir dosyanın iki farklı sürümüne sahip olmanız olabilir: biri yolda, diğeri değil.

Bunu çalıştırarak kontrol et

hangi çalıştırılabilir

ve

whereis executable

Sorunlarımı düzeltti ... Yürütülebilir dosyanın üç sürümü vardı, bunlardan sadece biri çevre için doğru bir şekilde derlenmişti.


0

/POSIX PATH kuralı için gerekçe

Kural şurada belirtildi: Bash'da çalıştırmak için neden çalıştırılabilir dosyadan veya komut dosyası adından önce ./ (dot-slash) gerekiyor? ama bunun neden iyi bir tasarım olduğunu düşündüğümü daha ayrıntılı olarak açıklamak istiyorum.

İlk olarak, kuralın açık bir tam sürümü:

  • yol içeriyorsa /(örn ./someprog. /bin/someprog, ./bin/someprog): CWD kullanılır ve PATH kullanılmaz
  • yol içermiyorsa /(örn. someprog): PATH kullanılır ve CWD kullanılmaz

Şimdi şunu varsayalım:

someprog

arayacaktı:

  • önce CWD'ye göre
  • sonraki PATH ile ilgili

Sonra, /bin/someprogdağıtımınızdan kaçmak istiyorsanız ve şunları yaptınız:

someprog

bazen işe yarayabilir, ancak diğerleri başarısız olur, çünkü başka bir ilgisiz someprogprogram içeren bir dizinde olabilirsiniz .

Bu nedenle, yakında bunun güvenilir olmadığını öğreneceksiniz ve PATH kullanmak istediğinizde her zaman mutlak yollar kullanacaksınız, bu nedenle PATH'ın amacını yeneceksiniz.

Bu yüzden PATH'nizde göreli yollara sahip olmak gerçekten kötü bir fikirdir. Sana bakıyorumnode_modules/bin .

Tersine, şu koşuyu varsayalım:

./someprog

Arama:

  • önce PATH'a göre
  • sonraki CWD'ye göre

Daha sonra, someprogbir git deposundan bir komut dosyası indirdiyseniz ve CWD'den çalıştırmak istiyorsanız, bunun çalıştırılacak gerçek program olduğundan asla emin olmazsınız, çünkü belki de dağıtımınız şunları içerir:

/bin/someprog

geçen yıl Noel'den sonra çok fazla içtikten sonra kurduğunuz paketten PATH içinde.

Bu nedenle, bir kez daha, ne çalıştırdığınızı bilmek için her zaman CWD'ye göre yerel komut dosyalarını tam yollarla çalıştırmak zorunda kalacaksınız:

"$(pwd)/someprog"

bu da son derece can sıkıcı olurdu.

Gelmek isteyebileceğiniz başka bir kural:

göreli yollar yalnızca PATH, yalnızca mutlak yollar CWD kullanır

ancak bir kez daha bu, kullanıcıları PATH olmayan komut dosyaları için her zaman mutlak yollar kullanmaya zorlar "$(pwd)/someprog".

/Yol arama kuralı hakkında sorununa çözüm hatırlamak için bir basit sunmaktadır:

  • eğik çizgi: kullanma PATH
  • eğik çizgi yok: sadece kullanın PATH

bu da, geçerli dizindeki dosyaların ya ./somefileveya olarak ifade edilebileceğine güvenerek, her zaman ne çalıştırdığınızı bilmenizi kolaylaştırır somefileve böylece bunlardan birine özel bir anlam verir.

Bazen, some/proggöreli olarak PATHarayamayacağınız biraz sinir bozucu , ama bunun için daha akılcı bir çözüm görmüyorum.



-2

Herkesin soruya büyük bir cevabı vardır ve evet, mutlak yolu eklemediğiniz sürece bu sadece geçerli dizinde çalıştırıldığında geçerlidir. Aşağıdaki örneklerime bakın.

Ayrıca, (dot-slash) çocuk klasörü tmp2 (/ tmp / tmp2) komutunu aldığımda ve (double dot-slash) kullandığında bana mantıklı geldi.

ÖRNEKLEM:

[fifiip-172-31-17-12 tmp]$ ./StackO.sh

Hello Stack Overflow

[fifi@ip-172-31-17-12 tmp]$ /tmp/StackO.sh

Hello Stack Overflow

[fifi@ip-172-31-17-12 tmp]$ mkdir tmp2

[fifi@ip-172-31-17-12 tmp]$ cd tmp2/

[fifi@ip-172-31-17-12 tmp2]$ ../StackO.sh

Hello Stack Overflow
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.