Di Linux, saya menggunakan stat --format="%s" FILE
, tetapi Solaris yang saya akses tidak memiliki perintah stat. Lalu apa yang harus saya gunakan?
Saya sedang menulis skrip Bash, dan tidak dapat menginstal perangkat lunak baru pada sistem.
Saya sudah mempertimbangkan untuk menggunakan:
perl -e '@x=stat(shift);print $x[7]' FILE
atau bahkan:
ls -nl FILE | awk '{print $5}'
Tapi tak satu pun dari ini terlihat masuk akal - menjalankan Perl hanya untuk mendapatkan ukuran file? Atau menjalankan 2 perintah untuk melakukan hal yang sama?
Jawaban:
wc -c < filename
(kependekan dari jumlah kata,-c
mencetak jumlah byte) adalah solusi portabel, POSIX . Hanya format keluaran yang mungkin tidak seragam di seluruh platform karena beberapa spasi mungkin ditambahkan di awal (yang merupakan kasus untuk Solaris).Jangan mengabaikan pengalihan input. Ketika file dikirimkan sebagai argumen, nama file dicetak setelah jumlah byte.
Saya khawatir itu tidak akan berfungsi untuk file biner, tetapi berfungsi dengan baik di Linux dan Solaris. Anda bisa mencobanya dengan
wc -c < /usr/bin/wc
. Selain itu, utilitas POSIX dijamin untuk menangani file biner , kecuali ditentukan lain secara eksplisit.sumber
wc -c < file
jika Anda tidak ingin nama file muncul.wc
dalam sebuah pipa harusread()
seluruh aliran untuk menghitung byte. Thels
/awk
solusi (dan sejenis) menggunakan system call untuk mendapatkan ukuran, yang harus menjadi waktu linear (versus O (ukuran))wc
menjadi sangat lambat terakhir kali saya melakukannya pada hard disk penuh. Cukup lambat sehingga saya bisa menulis ulang naskah sebelum yang pertama selesai, datang ke sini untuk mengingat bagaimana saya melakukannya lol.wc -c
; terlihat jauh lebih rapi tetapils
+awk
lebih baik untuk kecepatan / penggunaan sumber daya. Juga, saya hanya ingin menunjukkan bahwa Anda sebenarnya perlu melakukan pasca-proses hasilwc
juga karena pada beberapa sistem akan memiliki spasi sebelum hasil, yang mungkin perlu Anda hapus sebelum Anda dapat melakukan perbandingan.wc -c
bagus, tetapi tidak akan berfungsi jika Anda tidak memiliki akses baca ke file.Saya akhirnya menulis program saya sendiri (sangat kecil) untuk menampilkan ukurannya saja. Informasi lebih lanjut di sini: http://fwhacking.blogspot.com/2011/03/bfsize-print-file-size-in-bytes-and.html
Dua cara paling bersih menurut saya dengan alat Linux yang umum adalah:
Tetapi saya hanya tidak ingin mengetik parameter atau menyalurkan output hanya untuk mendapatkan ukuran file, jadi saya menggunakan bfsize saya sendiri.
sumber
stat
merupakan opsi bagi mereka.wc -c
membutuhkan 4090 msec pada file 10 MB vs "0" msecstat -c %s
, jadi saya setuju akan sangat membantu untuk memiliki solusi alternatif bahkan ketika mereka tidak menjawab pertanyaan yang diajukan.stat -c %s /usr/bin/stat
stat: illegal option -- c
usage: stat [-FlLnqrsx] [-f format] [-t timefmt] [file ...]
Meskipun
du
biasanya mencetak penggunaan disk dan bukan ukuran data sebenarnya, GNU coreutilsdu
dapat mencetak "ukuran nyata" file dalam byte:Tetapi itu tidak akan berfungsi di bawah BSD, Solaris, macOS, ...
sumber
brew install coreutils
dangdu -b
akan mencapai efek yang samawc
perlu membaca seluruh file sebelum memberikan hasil,du
langsung.du -b
dalam konteks yang sama sekali berbeda dalamdu
alasannya .lstat
panggilan, jadi kinerjanya tidak bergantung pada ukuran file. Lebih pendek daristat -c '%s'
, tetapi kurang intuitif dan berfungsi secara berbeda untuk folder (mencetak ukuran setiap file di dalamnya).du
bisa hampir digunakandu -A -B1
, tetapi masih mencetak hasil dalam kelipatan 1024B blok. Tidak berhasil mendapatkannya untuk mencetak jumlah byte. Bahkan pengaturanBLOCKSIZE=1
di lingkungan tidak membantu, karena blok 512B digunakan kemudian.Akhirnya saya memutuskan untuk menggunakan ls, dan bash array expansion:
Ini tidak terlalu bagus, tapi setidaknya hanya 1 fork + execve, dan tidak bergantung pada bahasa pemrograman sekunder (perl / ruby / python / apapun)
sumber
ls -ln FILE | { read _ _ _ _ size _ && echo "$size"; }
kebutuhan portabel tidak bercabang untuk langkah kedua dari pipeline, karena ia hanya menggunakan built-in, tetapi Bash 4.2.37 pada Linux bercabang dua kali (masih hanya satuexecve
).read _ _ _ _ size _ <<<"$(exec ls -ln /usr/bin/wc)" && echo "$size"
bekerja dengan garpu tunggal dan eksekutif tunggal, tetapi menggunakan file sementara untuk string di sini. Ini dapat dibuat portabel dengan mengganti here-string dengan here-document yang sesuai dengan POSX . BTW perhatikan bagianexec
dalam subkulit. Tanpa itu, Bash melakukan satu garpu untuk subkulit dan satu lagi untuk perintah yang berjalan di dalam. Ini adalah kasus dalam kode yang Anda berikan dalam jawaban ini. terlalu.-l
tidak berguna jika ada-n
. Mengutip POSIXls
manualnya :-n
: Hidupkan-l
(elo) pilihan, tapi ketika menulis pemilik file atau kelompok, menulis UID numerik file atau GID daripada pengguna atau grup nama, masing-masing. Menonaktifkan-C
,-m
dan-x
pilihan.Solusi tercepat lintas platform (hanya menggunakan garpu tunggal () untuk ls , tidak mencoba menghitung karakter sebenarnya, tidak memunculkan awk, perl, dll yang tidak diperlukan).
Diuji di MacOS, Linux - mungkin memerlukan sedikit modifikasi untuk Solaris:
Jika perlu, sederhanakan argumen ls , dan sesuaikan offset di $ {__ ln [3]}.
Catatan: akan mengikuti symlink.
sumber
BSD memiliki
stat
opsi yang berbeda dari GNU coreutils, tetapi kemampuannya serupa.Ini berfungsi di macOS (diuji pada 10.12), FreeBSD , NetBSD , dan OpenBSD .
sumber
stat
utilitas sama sekali.Saat memproses
ls -n
keluaran, sebagai alternatif dari array shell yang tidak portabel, Anda dapat menggunakan argumen posisi, yang merupakan satu-satunya array dan satu-satunya variabel lokal dalam shell standar. Bungkus penimpaan argumen posisi dalam sebuah fungsi untuk mempertahankan argumen asli ke skrip atau fungsi Anda.Ini membagi output
ln -dn
sesuai denganIFS
pengaturan variabel lingkungan saat ini , menetapkannya ke argumen posisi dan menggemakan yang kelima. The-d
Memastikan direktori ditangani dengan benar dan-n
menjamin bahwa nama pengguna dan grup tidak perlu diselesaikan, seperti dengan-l
. Selain itu, nama pengguna dan grup yang berisi spasi secara teoritis dapat merusak struktur garis yang diharapkan; mereka biasanya tidak diizinkan, tetapi kemungkinan ini masih membuat programmer berhenti dan berpikir.sumber
Jika Anda menggunakan
find
dari fileutils GNU:Sayangnya, implementasi lain
find
biasanya tidak mendukung-maxdepth
, atau-printf
. Ini adalah kasus untuk Solaris dan macOSfind
.sumber
size=$(test -f filename && find filename -printf '%s')
.-maxdepth
dimaksudkan untuk mencegahfind
rekursif (karenastat
OP yang perlu diganti tidak).find
Perintah Anda tidak ada-name
dantest
perintah tidak perlu.find
mencari parameternya secara rekursif untuk file yang cocok dengan kriteria yang diberikan. Jika parameternya bukan direktori, rekurinya adalah… cukup sederhana. Oleh karena itu saya pertama kali menguji itufilename
benar-benar file biasa yang ada, dan kemudian saya mencetak ukurannya menggunakanfind
yang tidak dapat digunakan kembali.find . -maxdepth 1 -type f -name filename -printf '%s'
hanya berfungsi jika file ada di direktori saat ini, dan mungkin masih memeriksa setiap file di direktori, yang mungkin lambat. Penggunaan yang lebih baik (bahkan lebih pendek!)find filename -maxdepth 1 -type f -printf '%s'
.Anda dapat menggunakan
find
perintah untuk mendapatkan beberapa set file (di sini file temp diekstrak). Kemudian Anda dapat menggunakandu
perintah untuk mendapatkan ukuran file dari setiap file dalam bentuk yang dapat dibaca manusia menggunakan-h
switch.KELUARAN:
sumber
Contoh Perl pertama Anda tidak terlihat tidak masuk akal bagi saya.
Karena alasan seperti inilah saya bermigrasi dari menulis skrip shell (di bash / sh dll.) Ke menulis semua kecuali skrip yang paling sepele di Perl. Saya menemukan bahwa saya harus meluncurkan Perl untuk persyaratan tertentu, dan ketika saya melakukannya lebih dan lebih, saya menyadari bahwa menulis skrip di Perl mungkin lebih kuat (dalam hal bahasa dan beragam perpustakaan yang tersedia melalui CPAN ) dan cara yang lebih efisien untuk mencapai apa yang saya inginkan.
Perhatikan bahwa bahasa skrip shell lainnya (misalnya python / ruby) pasti memiliki fasilitas serupa, dan Anda mungkin ingin mengevaluasinya untuk keperluan Anda. Saya hanya membahas Perl karena itulah bahasa yang saya gunakan dan saya kenal.
sumber
jika Anda memiliki Perl di Solaris Anda, maka gunakanlah. Jika tidak, ls dengan awk adalah pilihan terbaik Anda berikutnya, karena Anda tidak memiliki stat atau temuan Anda bukan GNU find.
sumber
Ada trik di Solaris yang pernah saya gunakan, jika Anda meminta ukuran lebih dari satu file, ia hanya mengembalikan ukuran total tanpa nama - jadi sertakan file kosong seperti / dev / null sebagai file kedua:
misalnya file perintah yang Anda inginkan / dev / null
Saya tidak dapat mengingat kembali perintah ukuran mana yang berfungsi untuk ls / wc / etc - sayangnya saya tidak memiliki kotak solaris untuk mengujinya.
sumber
di linux Anda dapat menggunakan
du -h $FILE
, apakah itu juga berfungsi di solaris?sumber
Apakah Anda mencoba du -ks | awk '{print $ 1 * 1024}'. Itu mungkin berhasil.
sumber