“Du -sh *” ve “du -sh ./*” arasındaki fark nedir?


Yanıtlar:


69
$ touch ./-c $ 'a \ n12 \ tb' foo
$ du -hs *
0 a
12 b
0 foo
Toplam 0

Gördüğünüz gibi, -cdosya bir seçenek olarak alındı duve bildirilmedi (ve totalnedeniyle satırı görüyorsunuz du -c). Ayrıca, çağrılan dosya a\n12\tbbize ave çağrılan dosyaların olduğunu düşündürüyor b.

$ du -hs -- *
0       a
12      b
0       -c
0       foo

Bu daha iyi. En azından bu sefer -cbir seçenek olarak alınmaz.

$ du -hs ./*
0       ./a
12      b
0       ./-c
0       ./foo

Bu daha iyi. ./Öneki önler -cbir seçenek ve yokluğu olarak çekilen ./önce bçıkış bir olduğunu belirtir içinde bvar dosya, ancak satır karakteri olan bir dosya vardır (ama aşağıyı görünüz 1 bu konuda daha parantezler için).

./Mümkün olduğunda öneki kullanmak iyi bir uygulamadır ve eğer değilse ve isteğe bağlı veriler için her zaman şunu kullanmalısınız:

cmd -- "$var"

veya:

cmd -- $patterns

Eğer cmddesteklemediği --seçeneklerin sonunu işaretlemek için, siz (bu seçime var ve için gibi belgelenmiş durumlar hariç, yazarına bir hata olarak bildirmeniz gerekir echo).

./*Sorunları çözmeyen durumlar vardır --. Örneğin:

awk -f file.awk -- *

adlı bir dosya varsa başarısız a=b.txtgeçerli dizinde (awk değişkeni ayarlar aiçin b.txtdosyayı işlemek için söylüyorum yerine).

awk -f file.awk ./*

./aGeçerli bir awk değişken adı olmadığı için sorun yok, bu yüzden ./a=b.txtdeğişken ataması olarak alınmıyor.

cat -- * | wc -l

-Geçerli dizinde adı verilen bir dosya varsa cat, bunun stdin'sinden okumasını söyler ( -çoğu metin işleme yardımcı programına ve cd/ için özeldir pushd).

cat ./* | wc -l

Tamam, çünkü ./-özel değil cat.

Gibi şeyler:

grep -l -- foo *.txt | wc -l

fooDosya adlarının yeni satır karakterleri içermediğini varsaydığı için yanlış olan dosyaların sayısını saymak için ( wc -lyeni satır karakterlerini, grepher dosya için çıkarılanları ve dosya adlarındakileri sayar ). Bunun yerine kullanmalısınız:

grep -l foo ./*.txt | grep -c /

(Her /karakter için sadece bir tane olabileceği için karakter sayımı daha güvenilirdir).

Özyinelemeli olarak grep, eşdeğer hile kullanmaktır:

grep -rl foo .//. | grep -c //

./* Gerçi bazı istenmeyen yan etkileri olabilir.

cat ./*

dosya başına iki karakter daha ekler; bu nedenle, daha önce argümanların + ortamın maksimum boyutunun sınırına erişirsiniz. Ve bazen ./bunun çıktıda bildirilmesini istemezsiniz . Sevmek:

grep foo ./*

Çıktısı olur:

./a.txt: foobar

yerine:

a.txt: foobar

Diğer özetler

1 . Yorumlarda yapılan tartışmayı takiben, burada bunu genişletmek zorunda olduğumu hissediyorum.

$ du -hs ./*
0       ./a
12      b
0       ./-c
0       ./foo

Yukarıda, ./her bir dosyanın başlangıcını işaretlemek, her bir dosya adının nerede başladığını (at ./) ve nerede biteceğini ( ./çıktının bir sonraki veya sonundan önceki satırda) açıkça tanımlayabileceğimiz anlamına gelir .

Bunun anlamı, bunun du ./*tersine) çıktısının du -- *bir senaryoda bu kadar kolay olmasa da güvenilir bir şekilde çözümlenmesidir.

Çıktı yine de bir terminale gittiğinde, bir dosya adının sizi kandırabileceği çok daha fazla yol vardır:

  • Kontrol karakterleri, kaçış dizileri işlerin görüntülenme şeklini etkileyebilir. Örneğin \r, imleci satırın başına getirir \b, imleci geri, \e[Cileri (çoğu terminalde) hareket ettirir
  • boşluk karakteri: en belirgin olandan başlayarak bir terminalde birçok karakter görünmez.
  • Çoğu yazı tipinde eğik çizgiyle aynı görünen Unicode karakterler var

    $ printf '\u002f \u2044 \u2215 \u2571 \u29F8\n'
    /    

    (tarayıcınızda nasıl göründüğüne bakın).

Bir örnek:

$ touch x 'x ' $'y\bx' $'x\n0\t.\u2215x' $'y\r0\t.\e[Cx'
$ ln x y
$ du -hs ./*
0       ./x
0       ./x
0       ./x
0       .∕x
0       ./x
0       ./x

Çok xama ykayıp.

GNULs gibi bazı araçlar , çıktı bir terminale girdiğinde yazdırılamayan karakterleri soru işareti (yerine (U + 2215) yazdırılabildiğini unutmayın ) ile değiştirir. GNU duyapmaz.

Kendilerini açıklamalarını sağlamanın yolları var:

$ ls
x  x   x?0?.∕x  y  y?0?.?[Cx  y?x
$ LC_ALL=C ls
x  x?0?.???x  x   y  y?x  y?0?.?[Cx

Bakın nasıl döndü ???bize söylendiği sonra lsbizim karakter kümesi ASCII olduğunu.

$ du -hs ./* | LC_ALL=C sed -n l
0\t./x$
0\t./x $
0\t./x$
0\t.\342\210\225x$
0\t./y\r0\t.\033[Cx$
0\t./y\bx$

$işaretleri hattının ucu, biz nokta böylece "x"vs "x "tüm basılamayan karakterler ve ASCII olmayan karakterlerini açık olan araç, bir ters eğik dizisi (tek başına iki ters ile temsil edilen eğik çizgi) ile temsil edilir. Bu GNU idi sed, tüm POSIX uyumlu seduygulamalarda aynı olması gerekir, ancak bazı eski seduygulamaların neredeyse yardımcı olmadıklarına dikkat edin .

$ du -hs ./* | cat -vte
0^I./x$
0^I./x $
0^I./x$
0^I.M-bM-^HM-^Ux$

(standart değil, aynı zamanda cat -Abazı uygulamalarda da oldukça yaygındır ). Bu yardımcı olur ve farklı bir temsil kullanır, ancak belirsizdir ( "^I"ve <TAB>aynı şekilde gösterilir).

$ du -hs ./* | od -vtc
0000000   0  \t   .   /   x  \n   0  \t   .   /   x      \n   0  \t   .
0000020   /   x  \n   0  \t   . 342 210 225   x  \n   0  \t   .   /   y
0000040  \r   0  \t   . 033   [   C   x  \n   0  \t   .   /   y  \b   x
0000060  \n
0000061

Bu standart ve açıktır (ve uygulamadan uygulamaya kadar tutarlıdır), ancak okunması kolay değildir.

yYukarıda asla ortaya çıkmadığını fark edeceksiniz . Bu tamamen ilgisiz bir meseledir , du -hs *bunun dosya adlarıyla hiçbir ilgisi yoktur, ancak not edilmelidir: dudisk kullanımını rapor ettiği için, zaten listelenen bir dosyaya başka bağlantılar bildirmez (tüm duuygulamalar sabit bağlantılar listelenmiş olsa bile böyle davranmaz. komut satırında).


+1, Güzel ve kapsamlı (söyleyebildiğim kadarıyla ^^). Özellikle "grep -c /" avantajını seviyorum. Ayrıca kayda değer: "./*" yerine "*" nin avantajı, Unix SSS’in (muhtemelen faqs.org. İirc’de) (çoğu kez) iyi cevaplarından birinde görünür. bir "-").
Olivier Dulac

… Ve adlarında yeni satırlara ve sekmelere sahip dosyalar olması kötü bir uygulama değil mi? Biliyorum ben hiç sınır adlarına deneyin [a-z0-9.+-].
Blacklight,

5
@BlacklightShining, çok var kötü araba çalmak, ama bu kötü pahalı bir araba var, özellikle (yeni satırlar göz ardı) araç kilidi bırakmak (script hassas veriler içeren bir sunucuda, ayrıcalıklı kullanıcı olarak çalışan ...) ya da sizi Engebeli bir alana ( /tmp) ya da çok sayıda pahalı arabaya sahip bir alana ( ) park edin $HOMEve bir soru-cevap sitesine gitmek daha da kötüydü ve hangi şartlarda (kilitli bir garajda, senaryoda) belirtmeden arabanızı kilitlememek her zaman iyidir
Kendi

1
@BlacklightShining, yeni satırlar sıra dışıdır ancak gömülü alanlar günümüzde, özellikle GUI aracılığıyla oluşturulan dosyalar için çok yaygındır.
alexis

2
@BlacklightShining, evet (ancak "b "veya gibi "a\bb") bir kullanıcıyı bir terminalde kandırabilir ancak çıktısını ayrıştırılan bir komut dosyasını değil du ./*. Muhtemelen bunun hakkında bir not eklemeliyim. Yarın yapacağım. Daha önce genel anlamda imtiyazlı demek istediğimi not edin root( rootelbette daha fazlasını uygular ). newlines izin verilir, görmezden gelmek bir hatadır. böceklerin sömürülme alışkanlığı var. Riski vaka bazında ölçmelisiniz. İyi kodlama uygulaması birçok durumda problemleri önleyebilir. Tabii ki SE'de farkındalık yaratmalıyız.
Stéphane Chazelas

6

*Ve ./*arasında hangi dosyaların listeleneceği ile ilgili hiçbir fark yoktur . Tek fark 2. formda olacaktır, her bir dosya ./önlerinde bir nokta eğik çizgiye sahip olacaktır , bu da tipik olarak geçerli dizini ifade eder.

.Dizinin, geçerli dizin için kısa bir gösterim olduğuna dikkat edin .

$ ls -la | head -4
total 28864
drwx------. 104 saml saml    12288 Jan 23 20:04 .
drwxr-xr-x.   4 root root     4096 Jul  8  2013 ..
-rw-rw-r--.   1 saml saml      972 Oct  6 20:26 abcdefg

Bu 2 listenin esasen aynı şey echoolduğuna, kabuğun neye genişleyeceğini görmek için kendinizi ikna edebilirsiniz .

$ echo *
$ echo ./*

Bu 2 komut, geçerli dizininizdeki tüm dosyaları listeler.

Örnekler

Bunun gibi bazı sahte veriler yapabiliriz:

$ touch file{1..5}
$ ll
total 0
-rw-rw-r--. 1 saml saml 0 Jan 24 07:14 file1
-rw-rw-r--. 1 saml saml 0 Jan 24 07:14 file2
-rw-rw-r--. 1 saml saml 0 Jan 24 07:14 file3
-rw-rw-r--. 1 saml saml 0 Jan 24 07:14 file4
-rw-rw-r--. 1 saml saml 0 Jan 24 07:14 file5

Şimdi yukarıdaki echokomutları kullandığımızda aşağıdaki çıktıyı görüyoruz:

$ echo *
file1 file2 file3 file4 file5
$ echo ./*
./file1 ./file2 ./file3 ./file4 ./file5

Bu fark gereksiz görünebilir, ancak dosya adlarını komut satırı üzerinden geçirdiğiniz çeşitli Unix komut satırı araçlarına garanti etmek istediğiniz durumlar vardır, başka bir şey yoktur!

Öyleyse neden kullan.

As Stephane'ın cevabı işaret @ nedeniyle Unix dosyaları ve dizinleri adlandırırken karakterler yasal ne doğası gereği, tehlikeli dosya adları onlar komut satırına çeşitli Unix komutları geçirilen yaparken beklenmedik yan etkilere sahip olan oluşturulabilir.

Sıklıkla, ./genişletilmiş dosya adlarının çeşitli Unix komutlarına argüman olarak iletildiğinde dosya adları olarak kabul edilmesini garanti altına almak için sıklıkla kullanılır.

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.