Yanıtlar:
$ touch ./-c $ 'a \ n12 \ tb' foo $ du -hs * 0 a 12 b 0 foo Toplam 0
Gördüğünüz gibi, -c
dosya bir seçenek olarak alındı du
ve bildirilmedi (ve total
nedeniyle satırı görüyorsunuz du -c
). Ayrıca, çağrılan dosya a\n12\tb
bize a
ve ç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 -c
bir seçenek olarak alınmaz.
$ du -hs ./*
0 ./a
12 b
0 ./-c
0 ./foo
Bu daha iyi. ./
Öneki önler -c
bir seçenek ve yokluğu olarak çekilen ./
önce b
çıkış bir olduğunu belirtir içinde b
var 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 cmd
desteklemediğ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.txt
geçerli dizinde (awk değişkeni ayarlar a
için b.txt
dosyayı işlemek için söylüyorum yerine).
awk -f file.awk ./*
./a
Geçerli bir awk değişken adı olmadığı için sorun yok, bu yüzden ./a=b.txt
değ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
foo
Dosya adlarının yeni satır karakterleri içermediğini varsaydığı için yanlış olan dosyaların sayısını saymak için ( wc -l
yeni satır karakterlerini, grep
her 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
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:
\r
, imleci satırın başına getirir \b
, imleci geri, \e[C
ileri (çoğu terminalde) hareket ettirirÇ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 x
ama y
kayıp.
GNU
Ls 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 du
yapmaz.
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 ls
bizim 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 sed
uygulamalarda aynı olması gerekir, ancak bazı eski sed
uygulamaları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 -A
bazı 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.
y
Yukarı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: du
disk kullanımını rapor ettiği için, zaten listelenen bir dosyaya başka bağlantılar bildirmez (tüm du
uygulamalar sabit bağlantılar listelenmiş olsa bile böyle davranmaz. komut satırında).
[a-z0-9.+-]
.
/tmp
) ya da çok sayıda pahalı arabaya sahip bir alana ( ) park edin $HOME
ve bir soru-cevap sitesine gitmek daha da kötüydü ve hangi şartlarda (kilitli bir garajda, senaryoda) belirtmeden arabanızı kilitlememek her zaman iyidir
"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
( root
elbette 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.
*
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 echo
olduğ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.
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 echo
komutları 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!
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.