Apa perbedaan antara du -sh * dan du -sh ./* ?
Catatan:Yang menarik bagi saya adalah * dan ./* bagian.
Jawaban yang Diterima:
$ touch ./-c $'an12tb' foo $ du -hs * 0 a 12 b 0 foo 0 total
Seperti yang Anda lihat, -c file diambil sebagai opsi untuk du dan tidak dilaporkan (dan Anda melihat total baris karena du -c ). Juga, file bernama an12tb membuat kami berpikir bahwa ada file bernama a dan b .
$ du -hs -- *
0 a
12 b
0 -c
0 foo
Itu lebih baik. Setidaknya kali ini -c tidak diambil sebagai pilihan.
$ du -hs ./*
0 ./a
12 b
0 ./-c
0 ./foo
Itu lebih baik. ./ awalan mencegah -c dari diambil sebagai opsi dan tidak adanya ./ sebelum b di output menunjukkan bahwa tidak ada b file di sana, tetapi ada file dengan karakter baris baru (tetapi lihat di bawah untuk penyimpangan lebih lanjut tentang itu).
Ini adalah praktik yang baik untuk menggunakan ./ awalan jika memungkinkan, dan jika tidak, dan untuk data arbitrer, Anda harus selalu gunakan:
cmd -- "$var"
atau:
cmd -- $patterns
Jika cmd tidak mendukung -- untuk menandai akhir opsi, Anda harus melaporkannya sebagai bug kepada pembuatnya (kecuali jika itu karena pilihan dan didokumentasikan seperti untuk echo ).
Ada kasus di mana ./* memecahkan masalah yang -- tidak. Misalnya:
awk -f file.awk -- *
gagal jika ada file bernama a=b.txt di direktori saat ini (mengatur variabel awk a ke b.txt alih-alih menyuruhnya memproses file).
awk -f file.awk ./*
Tidak ada masalah karena ./a bukan nama variabel awk yang valid, jadi ./a=b.txt tidak diambil sebagai tugas variabel.
cat -- * | wc -l
gagal jika ada file bernama - di direktori saat ini, seperti yang memberitahu cat untuk membaca dari stdinnya (- khusus untuk sebagian besar utilitas pemrosesan teks dan untuk cd /pushd ).
cat ./* | wc -l
tidak apa-apa karena ./- tidak khusus untuk cat .
Hal-hal seperti:
grep -l -- foo *.txt | wc -l
untuk menghitung jumlah file yang berisi foo salah karena menganggap nama file tidak mengandung karakter baris baru (wc -l menghitung karakter baris baru, yang dihasilkan oleh grep untuk setiap file dan yang ada dalam nama file itu sendiri). Anda harus menggunakan sebagai gantinya:
grep -l foo ./*.txt | grep -c /
(menghitung jumlah / karakter lebih dapat diandalkan karena hanya ada satu per nama file).
Untuk grep rekursif , trik yang setara adalah dengan menggunakan:
grep -rl foo .//. | grep -c //
./* mungkin memiliki beberapa efek samping yang tidak diinginkan.
cat ./*
menambahkan dua karakter lagi per file, sehingga akan membuat Anda mencapai batas ukuran maksimum argumen+lingkungan lebih cepat. Dan terkadang Anda tidak menginginkan ./ itu untuk dilaporkan dalam output. Seperti:
grep foo ./*
Akan menghasilkan:
./a.txt: foobar
bukannya:
a.txt: foobar
Penyimpangan lebih lanjut
. Saya merasa harus mengembangkannya di sini, mengikuti diskusi di komentar.
$ du -hs ./*
0 ./a
12 b
0 ./-c
0 ./foo
Di atas, ./ . itu menandai awal setiap file berarti kita dapat dengan jelas mengidentifikasi di mana setiap nama file dimulai (di ./ ) dan di mana ia berakhir (di baris baru sebelum ./ next berikutnya atau akhir keluaran).
Artinya adalah output dari du ./* , bertentangan dengan du -- * ) dapat diuraikan dengan andal, meskipun tidak semudah itu dalam skrip.
Namun, ketika output masuk ke terminal, ada banyak cara lain yang dapat menipu Anda dengan nama file:
-
Karakter kontrol, urutan pelarian dapat memengaruhi cara sesuatu ditampilkan. Misalnya,
rmemindahkan kursor ke awal baris,bmemindahkan kursor kembali,e[Cmaju (di sebagian besar terminal)… -
banyak karakter yang tidak terlihat di terminal dimulai dengan yang paling jelas:karakter spasi.
-
Ada karakter Unicode yang terlihat sama seperti garis miring di sebagian besar font
$ printf 'u002f u2044 u2215 u2571 u29F8n' / ⁄ ∕ ╱ ⧸
(lihat bagaimana hasilnya di browser Anda).
Contoh:
$ touch x 'x ' $'ybx' $'xn0t.u2215x' $'yr0t.e[Cx'
$ ln x y
$ du -hs ./*
0 ./x
0 ./x
0 ./x
0 .∕x
0 ./x
0 ./x
Banyak x tapi y hilang.
Beberapa alat seperti GNU ls akan mengganti karakter yang tidak dapat dicetak dengan tanda tanya (perhatikan bahwa ∕ (U+2215) dapat dicetak) ketika output masuk ke terminal. GNU du tidak.
Ada beberapa cara untuk membuat mereka menampakkan diri:
$ 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
Lihat caranya ∕ beralih ke ??? setelah kami memberi tahu ls bahwa set karakter kita adalah ASCII.
$ du -hs ./* | LC_ALL=C sed -n l0t./x$0t./x $0t./x$0t.342210225x$0t./thn0t.
Linux