Cd neden bir program değil?


128

Neden cdbir program olmadığını her zaman merak etmişimdir , fakat cevabı bulamadım.

Neden böyle olduğunu bilen var mı?



1
Orijinal unix cdkomutunun ayrı bir program olduğunu (nerede bulamıyorum) okuduğumu hatırlıyorum . Kabuk etmedi özel o bunu ele fork, sadece exec. Ve ne zaman cdyapıldı, idam sh. Bunun gerçek bir hikaye olup olmadığını bilmiyorum.
camh

Mesele ne olurdu? Özel işlem ekleyecekseniz, chdirsistem çağrısını da çağırabilir . kaynaklar: v1 v5 v7 (Bourne kabuğuyla ilk versiyon)
Mikel

2
@ camh, bu gerçek bir hikaye. Okudum de Dennis M. Ritchie tarafından yazılan bir makalede, “Unix Zaman paylaşımı Sisteminin Evrimi” in, AT & T Bell Laboratuvarları Teknik Dergisi 63 (6), Bölüm 2, Ekim 1984. o
jlliagre

@Mikel: Anlamsız göründüğü konusunda hemfikirim, ancak cdokuduğum hakkında bir hikaye aktarıyordum . Onun yönü konusunda açıkça yanlıştım, şimdi jlliagre ayrıntılarla dolu.
camh

Yanıtlar:


171

cdKomut doğru, "geçerli çalışma dizinini" değiştirir?

"geçerli çalışma dizini", her işlem için benzersiz olan bir özelliktir.

Yani, eğer cdbir program olsaydı şöyle çalışırdı:

  1. cd foo
  2. cdsüreç başlar
  3. cdsüreç dizini değiştirir cd süreci için
  4. cdişlem çıktığında
  5. Kabuğunuz hala geçerli çalışma dizini de dahil olmak üzere başlamadan önce aynı duruma sahiptir.

8
Beş adımınız doğrudur, ancak “eğer cdböyle bir şekilde çalışacak bir program olsaydı” cd, harici program uygulamasında kullanıldığında “olması gerektiği gibi” olur .
jlliagre

1
Bir sistem programcısı olmamak, ya da kabukla etkileşime giren içeri ve dışarı hakkında derin bir bilgiye sahip olmamak, kabuğun mevcut çalışma dizinini ortaya çıkarmasını beklerdim ve cd bu özelliğe erişen ve değiştiren bir program olmasını beklerdim. Bu cevaba baktıktan sonra, bunun aslında pek çok nedenden dolayı nasıl çalıştığının altından optimal olduğunu anlamak.
Jason,

108

cdkabuk yerleşik olmasının yanı sıra , aslında POSIX uyumlu işletim sistemlerinde de bir programdır . Onlar gerekir gibi düzenli programlar için bağımsız çalıştırılabilir sağlamak cd. Bu örneğin Solaris , AIX , HP-UX ve OS X için olan durumdur .

Açıkçası, cdharici uygulama mevcut kabuk dizinini değiştirmediğinden bir yerleşik hala zorunludur. Bununla birlikte, ikincisi hala faydalı olabilir. POSIX'in bu cdkomutun nasıl kullanılabileceğini öngördüğünü gösteren bir örnek :

find . -type d -exec cd {} \;

Bir POSIX sisteminde bu oneliner, içeri girmenize izin verilmeyen tüm dizinler için bir hata mesajı bildirir cd. Çoğu Gnu / Linux dağıtımında, bu hata iletisiyle başarısız olur:

find: `cd': No such file or directory

Ve orjinal Unix yazarlarından birinin " Neden cd bir program değil? " Sorusunun cevabı . Çok erken bir Unix uygulamasında cd( chdiro sırada yazıldığından ) harici bir programdı. forkİlk uygulandıktan sonra beklenmedik bir şekilde çalışmayı durdurdu .

Dennis Ritchie'den alıntı :

Sevinmemizin ortasında, chdir (geçerli dizini değiştir) komutunun çalışmayı durdurduğu tespit edildi. Çatal ilavesinin chdir çağrısını nasıl kırabileceği konusunda çok fazla kod ve endişeli içgüdü okundu. Sonunda gerçeği doğdu: eski sistemde chdir sıradan bir emirdi; terminale ekli (benzersiz) işlemin geçerli dizinini ayarladı. Yeni sistemde, chdir komutu, yürütmek için oluşturulan işlemin geçerli dizinini doğru bir şekilde değiştirdi, ancak bu işlem derhal sonlandırıldı ve ana kabuğu üzerinde hiçbir etkisi olmadı! Chdir'yi kabuk içinde dahili olarak yürütülen özel bir komut yapmak gerekliydi. Birkaç komut benzeri fonksiyonun aynı özelliğe sahip olduğu, örneğin giriş olduğu ortaya çıktı.

Kaynak: Dennis M. Ritchie, “ Unix Zaman Paylaşma Sisteminin Gelişimi ”, AT&T Bell Laboratuvarları Teknik Dergisi 63 (6), Bölüm 2, Ekim 1984, s.1577–93

Unix Versiyon 1 (Mart 1971) chdir manuel sayfa durumları:

Her komutu yürütmek için yeni bir işlem oluşturulduğundan, normal bir komut olarak yazılmışsa chdir etkisiz olur. Bu nedenle Shell tarafından tanınır ve yürütülür.


10
... öyleyse, görünüşe göre, POSIX bağımsız bir cdçalıştırılabilir olmasını zorunlu kılar , ancak hiçbir şey yapmamasını zorunlu tutar (yanlış argümanlarla çağrılırsa muhtemelen hata mesajları göndermesi dışında). Tuhaf.
Ilmari Karonen

4
Doğru, doğruysa, POSIX’teki en aptalca şey bu olmazdı.
Kaz,

5
POSIX cd sayfa aynı zamanda "cd geçerli kabuk yürütme ortamı etkilediği için, her zaman bir kabuk düzenli yerleşik olarak sağlanır." Diyor.
Mikel

6
@Kaz, tamamen farklı şeyler değiller. Aynı şeyi yaparlar, ancak yalnızca yerleşik olan mevcut kabuğu etkiler.
jlliagre

13
@Kaz: Lütfen sadece bir gerçeği rapor ederken aptallık deme. POSIX ile hemfikir olabilir ya da aynı fikirde olmayabilirsin, ancak haberciyi vurma.
jlliagre

47

Bash girişinden ( Bir kabuk nedir? ):

Kabuklar, ayrıca, ayrı bir yardımcı program aracılığıyla edinilmesi imkansız veya uygunsuz olan, işlevselliği uygulayan küçük bir dizi yerleşik komut da sağlar. Örneğin, cd, break, continue, ve execdoğrudan kabuğun kendisinin işlemek için) kabuğun dışına uygulanması mümkün değildir. history, getopts, kill, Veya pwdbuiltins, diğerleri arasında ayrı araçlar olarak uygulanabilecek, ama yerleşik komutlar kullanmak daha uygundur. Tüm kabuk yerleşikleri sonraki bölümlerde açıklanmıştır.


29

Bu yıl April Fool's için, bağımsız bir versiyonunucd yazdım .

Kimse şaka alamadı. İç çekmek.

cdKabuğun içine yerleştirilmesi gerektiğinden emin olmayan herkes indirmeli, inşa etmeli ve denemelidir.

Adam sayfasını da oku. :)


Gerçekten kullanışlı kod! :-)
dschulz

6
Gnu / Linux'u daha POSIX uyumlu hale getirmek için çalışan birisini görmek güzel. Uygulamanız sadece iyi bir şaka değil aynı zamanda Linux dağıtımlarından eksik olan bir şey ...
jlliagre

8
Sanırım POSIX sorununu aktararak gelecek yıl tekrar deneyeceğim. ;)
Warren Young

6 yıl sonra: Peki ya sen?
Peter A. Schneider

@ PeterA.Schneider: Şaka yaptığımın net olduğunu düşündüm, bu yüzden açık olmak gerekirse, hayır, bunu şu anda işletim sistemi olan Cygwin gibi işletim sistemleri ve işletim sistemi benzeri projeler haline getirmek için çaba harcayacağım. eksikliği /bin/cd. Kodumu alıp kendi kişisel arayışını yapmak istiyorsan, bunu yapabilirsin.
Warren Young,

4

Kabuktaki cdkomut ayrı bir işlem olamaz çünkü Unix'te farklı bir işlemin geçerli çalışma dizinini değiştirecek mekanizma yoktur (ana işlem değil).

Eğer cdfarklı bir süreç oldu o zaman Unix mümkün değildir üst (kabuk), geçerli çalışma dizini değiştirmek gerekir. Bunun yerine cdözel bir komut içinde yerleşiktir. Kabuk kendi geçerli çalışma dizinini değiştirme chdir()ve fchdir()değiştirme gibi işlevleri çağırır .

Not: Çekirdek, her işlem için geçerli çalışma dizininin inode numarasını saklar. Çocuk süreci cwd, ebeveyninden miras kalıyor .


0

cd bir kabuk yerleşik komutudur. Olduğu kadar kolay. Adam cd her şeyi söylüyor. cd komutu, çalışma dizinini tüm tercümanlar ve (dişli bir ortamda) tüm iş parçacıkları için değiştirir.


Çünkü kabuk şu andaki çalışma direktifleriniz ($ PDW ...) veya cdable_vars ile ilgilenen ortamdır. Bu yerleşik sonuç, kullanıcı tarafından görülebilen tüm komutların geçerli çalışma dizinini değiştirmesi gerektiği şeklindedir. Bu şekilde test edebilirsiniz: bash'i cd.c olmadan derleyin ve tüm cdable_vars ortamlarına dikkat etmeye çalışan kendi cd betiğinizi yazmayı deneyin. Bu soru da daha bir geliştirici ile ilgili. Bahse girerim bu soruyu daha derinlemesine cevaplayabilirler.

2
Yerleşik olan çok iyi bir teknik sebep var cd. Size en üst sıradaki cevapları okumanızı ve yanıtınızın nasıl geliştirilebileceğini düşünmenizi öneririm.
Thorbjørn Ravn Andersen

Sıraladığım en yüksek cevap, okuduğum en kötü cevaptı! Ama ha? Ben kimim!

3
Fakat nedenini soruyor .
Thorbjørn Ravn Andersen

-1

İnsanların cevaplarında eksik olan bir şeyin mevcut dizinin her programın değiştirebileceği bir ortam değişkeni olduğunu düşünüyorum. Geçerli ortam değişkenleri listenizi görmek için 'export' komutunu kullanırsanız, şunları yapacaksınız:

declare -x PWD="/home/erfan"

sonuçlarında. Böylece 'cd' komutu ile sadece bu iç değişkeni değiştirmek istiyoruz. Bence denersek, PWD değişkenini kabuğundaki herhangi bir pty'nin içinde bulabiliriz. Sevmek:

cder    #change current PTY $PWD variable

Ama bence normal durumlarda gerek yok. Başka bir deyişle, tanımlanan iç değişkenini değiştirmek için bash'den (veya herhangi bir kabuktan) yardım alırız.


3
Bourne mermilerinin mevcut çalışma dizinini (CWD) $ PWD olarak gösterdiği doğru olsa da, birincil depolama yeri bu değil; Asıl konum çekirdeğin işlem başına yapısıdır. Bu nedenle CWD'nin "bir ortam değişkeni" olduğunu söylemek yanlıştır. Sizin önerdiğiniz şekilde işe yaradıysa, bu C iki astarı .., başlattığınız yolu değil, yolu yazdırır : #include <stdlib.h> int main(void) { chdir(".."); puts(getenv("PWD")); }(C kabukları bu arada CWD'yi% cwd olarak gösterir.)
Warren Young

uygulamanıza başka bazı satırlar ekleyelim. #include <stdlib.h> int main (void) {chdir (".."); koyar (getenv ( "PWD")); setenv (P "PWD", "/", 1); koyar (getenv ( "PWD")); } Sonuç olarak neye sahip olacağız?
Erfankam

3
Bu sadece CWD üzerinde hiçbir yan etkisi olmayan bir değişkenin değerinin üzerine yazacaktır. Bu şunu göstermek için daha iyi bir testtir: #include <unistd.h> int main(void) { char ac[99]; setenv("PWD", "/", 1); puts(getcwd(ac, sizeof(ac))); }Programı başlattığınız dizini değil gösterecektir /.
Warren Young

Her işlemin bir çalışma dizini ve yol değişkeni olduğunu düşünüyorum. Böylece chdir tarafından sadece sürecin bu niteliğini değiştirirsiniz. Shell'in de bu niteliği var ve cd ile bu niteliği değiştiriyoruz.
Erfankam

4
Hayır, sana $PWDsadece Bourne kabuğuna bir anlamı olduğunu söylüyorum . Bu sadece kabuk için komut dosyalarını kabukla bildiği bir şeyi iletmek için bir yoldur, bu yüzden pwdonu bulmak için aramaları gerekmez . Değerine bağlı olarak herhangi bir bağımsız program $PWDgüvenilmez olacaktır.
Warren Young
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.