शेल में फ़ाइल आकार (बाइट्स में) प्राप्त करने का पोर्टेबल तरीका?


121

लिनक्स पर, मैं उपयोग stat --format="%s" FILEकरता हूं, लेकिन मेरे पास सोलारिस का उपयोग स्टेट कमांड के पास नहीं है। फिर मुझे क्या उपयोग करना चाहिए?

मैं बैश स्क्रिप्ट लिख रहा हूं, और वास्तव में सिस्टम पर कोई नया सॉफ़्टवेयर स्थापित नहीं कर सकता।

मैंने पहले ही उपयोग करने पर विचार कर लिया है:

perl -e '@x=stat(shift);print $x[7]' FILE

या और भी:

ls -nl FILE | awk '{print $5}'

लेकिन इनमें से कोई भी समझदार नहीं है - केवल फ़ाइल आकार प्राप्त करने के लिए पर्ल चलाने? या 2 कमांड चलाने के लिए एक ही है?


1
अच्छी तरह से एक bash स्क्रिप्ट है सॉफ्टवेयर, और यदि आप सिस्टम पर कि रख सकते हैं, आप सॉफ्टवेयर स्थापित कर सकते हैं।
बस किसी को 11

4
तकनीकी रूप से - सच। मेरा मतलब था कि मेरे पास रूट विशेषाधिकार नहीं हैं, और मैं नए पैकेज स्थापित नहीं कर सकता। निश्चित रूप से घर में स्थापित करना संभव है। लेकिन वास्तव में नहीं जब मुझे स्क्रिप्ट बनाना है जो पोर्टेबल है, और "एक्स" मशीनों पर स्थापना, नए अतिरिक्त पैकेज मुश्किल हो जाते हैं।

जवाबों:


207

wc -c < filename(शब्द गणना के लिए संक्षिप्त, -cबाइट की गिनती प्रिंट करता है) एक पोर्टेबल, पोसिक्स समाधान है। केवल आउटपुट स्वरूप प्लेटफ़ॉर्म पर समान नहीं हो सकता है क्योंकि कुछ रिक्त स्थान पूर्वनिर्मित हो सकते हैं (जो कि सोलारिस के लिए मामला है)।

इनपुट पुनर्निर्देशन को छोड़ें नहीं। जब फ़ाइल को एक तर्क के रूप में पारित किया जाता है, तो फ़ाइल का नाम बाइट गिनती के बाद मुद्रित किया जाता है।

मुझे चिंता थी कि यह बाइनरी फ़ाइलों के लिए काम नहीं करेगा, लेकिन यह लिनक्स और सोलारिस दोनों पर ठीक काम करता है। आप इसके साथ कोशिश कर सकते हैं wc -c < /usr/bin/wc। इसके अलावा, POSIX उपयोगिताओं को बाइनरी फ़ाइलों को संभालने की गारंटी दी जाती है , जब तक कि अन्यथा स्पष्ट रूप से निर्दिष्ट न हो।


67
या सिर्फ wc -c < fileअगर आप फ़ाइल नाम प्रदर्शित नहीं करना चाहते हैं।
कैफे

34
अगर मैं गलत नहीं हूँ, हालाँकि, wcएक पाइप लाइन read()में बाइट्स गिनने के लिए पूरी स्ट्रीम होनी चाहिए । ls/ awkसमाधान (और इसी तरह) एक सिस्टम कॉल का उपयोग आकार, जो प्राप्त करने के लिए करना चाहिए रैखिक समय (बनाम हे (आकार))
jmtd

1
मुझे याद है wcकि पिछली बार जब मैंने ऐसा किया था, तो पूरी हार्ड डिस्क पर। यह काफी धीमा था कि मैं स्क्रिप्ट को फिर से लिख पाऊं, इससे पहले कि वह खत्म हो जाए, मुझे याद आया कि मैंने यह कैसे किया।
कैमिलो मार्टिन

6
मैं उपयोग नहीं करेगा wc -c; यह ज्यादा नटखट दिखता है लेकिन गति / संसाधन उपयोग के लिए ls+ awkबेहतर है। इसके अलावा, मैं केवल यह बताना चाहता था कि आपको वास्तव में परिणाम के बाद की प्रक्रिया की आवश्यकता है wcक्योंकि कुछ प्रणालियों पर परिणाम से पहले यह व्हाट्सएप होगा, जिसे तुलना करने से पहले आपको पट्टी करने की आवश्यकता हो सकती है।
हरविकाल

3
wc -cमहान है, लेकिन यह काम नहीं करेगा यदि आपके पास फ़ाइल तक पहुंच नहीं है।
सिलास

41

मैंने अपना आकार लिखने के लिए अपना कार्यक्रम (वास्तव में छोटा) लिखना समाप्त कर दिया। अधिक जानकारी यहाँ: http://fwhacking.blogspot.com/2011/03/bfsize-print-file-size-in-bytes-and.html

आम लिनक्स उपकरणों के साथ मेरी राय में दो सबसे साफ तरीके हैं:

$ stat -c %s /usr/bin/stat
50000

$ wc -c < /usr/bin/wc
36912

लेकिन मैं सिर्फ टाइपिंग पैरामीटर नहीं बनना चाहता हूं या केवल फाइल का आकार पाने के लिए आउटपुट को पाइप करता हूं, इसलिए मैं अपने खुद के bfsize का उपयोग कर रहा हूं।


2
समस्या वर्णन की पहली पंक्ति में कहा गया है कि स्टेटमेंट एक विकल्प नहीं है, और wc -c एक साल से अधिक समय के लिए शीर्ष उत्तर है, इसलिए मुझे यकीन नहीं है कि इस उत्तर का क्या मतलब है।

22
बिंदु मेरे जैसे लोग हैं, जो गूगल में इस तो सवाल यह खोजने के लिए और में है stat है उनके लिए एक विकल्प।
यो

3
मैं एक एम्बेडेड सिस्टम पर काम कर रहा हूं, जहां wc -c10 एमबी फ़ाइल बनाम "0" एमएसईसी पर 4090 एमएसईसी लेता है stat -c %s, इसलिए मैं मानता हूं कि वैकल्पिक समाधान के लिए भी उपयोगी है जब वे सटीक प्रश्न का उत्तर नहीं देते हैं।
राबर्ट काल्होन

3
"स्टेट -c" पोर्टेबल नहीं है / यह MacOS पर उसी तरह के तर्कों को स्वीकार नहीं करता है जैसा कि लिनक्स पर करता है। बड़ी फ़ाइलों के लिए "wc -c" बहुत धीमी होगी।
ऑरवेलोफाइल

2
स्टेट पोर्टेबल भी नहीं है। stat -c %s /usr/bin/stat stat: illegal option -- c usage: stat [-FlLnqrsx] [-f format] [-t timefmt] [file ...]

27

भले ही duआमतौर पर डिस्क उपयोग प्रिंट करता है और वास्तविक डेटा आकार नहीं होता है, GNU कोरुटिल duबाइट्स में फ़ाइल के "स्पष्ट आकार" को प्रिंट कर सकता है:

du -b FILE

लेकिन यह BSD, Solaris, macOS, के तहत काम नहीं करेगा ...


3
MacOS X पर, brew install coreutilsऔर gdu -bउसी प्रभाव को प्राप्त करेगा
जोस अल्बन

1
मैं इस पद्धति को पसंद करता हूं क्योंकि wcपरिणाम देने के लिए पूरी फाइल को पढ़ने की जरूरत है, duतत्काल है।
कज़िनकोकेन

2
POSIX का तर्कdu -b में एक पूरी तरह से अलग संदर्भ में उल्लेख है । du
पलक

यह केवल lstatकॉल का उपयोग करता है , इसलिए इसका प्रदर्शन फ़ाइल आकार पर निर्भर नहीं करता है। कम से stat -c '%s'कम, लेकिन कम सहज ज्ञान युक्त और फ़ोल्डरों के लिए अलग तरह से काम करता है (प्रत्येक फ़ाइल के आकार प्रिंट)।
पेलेक

FreeBSDdu का उपयोग बंद कर सकते हैं du -A -B1, लेकिन यह अभी भी 1024B ब्लॉकों के गुणकों में परिणाम प्रिंट करता है। बाइट्स काउंट प्रिंट करने के लिए इसे प्राप्त करने का प्रबंधन नहीं किया। यहां तक ​​कि BLOCKSIZE=1environemnt में सेटिंग मदद नहीं करती है, क्योंकि 512B ब्लॉक तब उपयोग किया जाता है।
पालेक

13

अंत में मैंने ls का उपयोग करने का निर्णय लिया, और ऐश सरणी विस्तार:

TEMP=( $( ls -ln FILE ) )
SIZE=${TEMP[4]}

यह वास्तव में अच्छा नहीं है, लेकिन कम से कम यह केवल 1 कांटा + निष्पादित करता है, और यह माध्यमिक प्रोग्रामिंग भाषा (पर्ल / रूबी / पायथन / जो कुछ भी) पर भरोसा नहीं करता है


बस एक तरफ - 'एल' में 'एल' की आवश्यकता नहीं है; '-n' ठीक वैसा ही है जैसा '-ln'
13:13 बजे वर्जित

नहीं यह नहीं। बस आउटपुट की तुलना करें।

1
एक का अनुमान है कि पोर्टेबल ls -ln FILE | { read _ _ _ _ size _ && echo "$size"; }जरूरतों को पाइपलाइन के दूसरे चरण के लिए कांटा नहीं चाहिए, क्योंकि यह सिर्फ बिल्ट-इन का उपयोग करता है, लेकिन लिनक्स फोर्क्स पर बैश 4.2.37 दो बार (अभी भी केवल एक है execve, हालांकि)।
पालेक

read _ _ _ _ size _ <<<"$(exec ls -ln /usr/bin/wc)" && echo "$size"एकल कांटा और एकल निष्पादन के साथ काम करता है, लेकिन यह यहां-स्ट्रिंग के लिए एक अस्थायी फ़ाइल का उपयोग करता है। यह POSX अनुरूप के साथ यहां-स्ट्रिंग की जगह पोर्टेबल बनाया जा सकता है यहाँ-दस्तावेज़execसब्मिट में BTW नोट करें । उसके बिना, बैश एक उपसमूह के लिए एक कांटा करता है और दूसरा अंदर चलने वाले कमांड के लिए। यह उस कोड में मामला है जो आप इस उत्तर में प्रदान करते हैं। भी।
पालेक

1
की -lउपस्थिति में शानदार है -n। का हवाला देते हुए POSIX lsमैनपेज : -nचालू करें: -l(ell) विकल्प है, लेकिन जब फ़ाइल के स्वामी या समूह लेखन, फ़ाइल का सांख्यिक यूआईडी या GID बल्कि बारे में उपयोगकर्ता या समूह नाम से क्रमश। अक्षम -C, -mऔर -xविकल्प।
पालेक

8

क्रॉस प्लेटफ़ॉर्म सबसे तेज़ समाधान (केवल एलएस के लिए एकल कांटा () का उपयोग करता है , वास्तविक वर्णों को गिनने का प्रयास नहीं करता है, अनावश्यक आवेग, पर्ल, आदि को स्पॉन नहीं करता है)।

MacOS, लिनक्स पर परीक्षण किया गया - सोलारिस के लिए मामूली संशोधन की आवश्यकता हो सकती है:

__ln=( $( ls -Lon "$1" ) )
__size=${__ln[3]}
echo "Size is: $__size bytes"

यदि आवश्यक हो, ls तर्कों को सरल करें , और $ {__ ln [3]} में ऑफसेट समायोजित करें।

नोट: सिम्बलिंक का पालन करेगा।


1
या इसे एक शेल स्क्रिप्ट में डालें: ls -Lon "$ 1" | awk '{प्रिंट $ 4}'
लूसियानो

1
@Luciano मैं तुम्हें पूरी तरह से की बात याद है लगता है forking नहीं और में एक कार्य कर रही पार्टी के बजाय स्ट्रिंग के लिए बैश यूनिक्स का एक बहुत एक अक्षम फैशन में एक साथ आदेशों का उपयोग करने से।
ऑरवेलोफिल

8

बीएसडी के पास statजीएनयू कोरुटिल्स एक से अलग विकल्प हैं, लेकिन समान क्षमताएं हैं।

stat -f %z <file name> 

यह macOS (10.12 पर परीक्षण किया गया), FreeBSD , NetBSD और OpenBSD पर काम करता है ।


statहालांकि सोलारिस में उपयोगिता नहीं है ।
पालेक

6

ls -nआउटपुट को संसाधित करते समय, बीमार-पोर्टेबल शेल सरणियों के विकल्प के रूप में, आप स्थिति संबंधी तर्कों का उपयोग कर सकते हैं, जो एकमात्र सरणी बनाते हैं और मानक शेल में एकमात्र स्थानीय चर हैं। अपनी स्क्रिप्ट या फ़ंक्शन के मूल तर्कों को संरक्षित करने के लिए एक फ़ंक्शन में स्थितीय तर्कों का अधिलेखित करें।

getsize() { set -- $(ls -dn "$1") && echo $5; }
getsize FILE

यह ln -dnवर्तमान IFSपर्यावरण चर सेटिंग्स के अनुसार आउटपुट को विभाजित करता है, इसे स्थितिगत तर्कों को निर्दिष्ट करता है और पांचवें को एको करता है। यह -dसुनिश्चित करता है कि निर्देशिकाओं को ठीक से संभाला जाए और -nआश्वासन दिया जाए कि उपयोगकर्ता और समूह के नामों को हल करने की आवश्यकता नहीं है, इसके विपरीत -l। इसके अलावा, व्हाट्सएप वाले उपयोगकर्ता और समूह के नाम सैद्धांतिक रूप से अपेक्षित लाइन संरचना को तोड़ सकते हैं; वे आमतौर पर अस्वीकृत हो जाते हैं, लेकिन यह संभावना अभी भी प्रोग्रामर को रोकती है और सोचती है।


5

यदि आप findGNU फ़ाइल से उपयोग करते हैं :

size=$( find . -maxdepth 1 -type f -name filename -printf '%s' )

दुर्भाग्य से, अन्य कार्यान्वयन findआमतौर पर समर्थन नहीं करते हैं -maxdepth, न ही -printf। यह उदाहरण है उदाहरण के लिए Solaris और macOS find


FYI करें maxdepth की जरूरत नहीं है। इसे फिर से लिखा जा सकता है size=$(test -f filename && find filename -printf '%s')
पालक

@Palec: -maxdepthको findपुनरावर्ती होने से रोकने का इरादा है ( statजिसके बाद से ओपी को बदलने की आवश्यकता नहीं है)। आपकी findकमांड अनुपलब्ध है -nameऔर testकमांड आवश्यक नहीं है।
अगली सूचना तक रोक दिया गया।

@DennisWilliamson findदिए गए मापदंड से मेल खाने वाली फ़ाइलों के लिए अपने मापदंडों को पुनरावर्ती खोजता है। यदि पैरामीटर निर्देशिका नहीं हैं, तो पुनरावृत्ति ... काफी सरल है। इसलिए मैं पहली बार परीक्षण करता हूं कि filenameयह वास्तव में एक मौजूदा साधारण फ़ाइल है, और फिर मैं इसका आकार प्रिंट करता हूं जिसका उपयोग findकहीं नहीं है।
पालेक

1
find . -maxdepth 1 -type f -name filename -printf '%s'केवल तभी काम करता है जब फ़ाइल वर्तमान निर्देशिका में है, और यह अभी भी निर्देशिका में प्रत्येक फ़ाइल की जांच कर सकती है, जो धीमी हो सकती है। बेहतर उपयोग (कम भी!) find filename -maxdepth 1 -type f -printf '%s'
पलक

3

आप findफ़ाइलों के कुछ सेट प्राप्त करने के लिए कमांड का उपयोग कर सकते हैं (यहाँ अस्थायी फ़ाइलें निकाली गई हैं)। फिर आप स्विच duका उपयोग करके मानव फ़ाइल को पढ़ने योग्य रूप में प्रत्येक फ़ाइल का आकार प्राप्त करने के लिए कमांड का उपयोग कर सकते हैं -h

find $HOME -type f -name "*~" -exec du -h {} \;

उत्पादन:

4.0K    /home/turing/Desktop/JavaExmp/TwoButtons.java~
4.0K    /home/turing/Desktop/JavaExmp/MyDrawPanel.java~
4.0K    /home/turing/Desktop/JavaExmp/Instream.java~
4.0K    /home/turing/Desktop/JavaExmp/RandomDemo.java~
4.0K    /home/turing/Desktop/JavaExmp/Buff.java~
4.0K    /home/turing/Desktop/JavaExmp/SimpleGui2.java~

2

आप पहले पर्ल उदाहरण मेरे लिए अनुचित नहीं लगते।

यह इस तरह के कारणों के लिए है कि मैंने शेल स्क्रिप्ट (बैश / श आदि में) लिखने से लेकर पेरल में सबसे अधिक तुच्छ लिपियों तक सब लिखा है। मैंने पाया कि मैं विशेष आवश्यकताओं के लिए पर्ल लॉन्च करने जा रहा था, और जैसा कि मैंने अधिक से अधिक किया, मुझे एहसास हुआ कि पर्ल में स्क्रिप्ट लिखना संभवतः एक अधिक शक्तिशाली था (भाषा के संदर्भ में और सीपीएएन के माध्यम से उपलब्ध पुस्तकालयों की विस्तृत सरणी ) और जो मैं चाहता था उसे प्राप्त करने के लिए अधिक कुशल तरीका।

ध्यान दें कि अन्य शेल-स्क्रिप्टिंग भाषाओं (जैसे कि अजगर / माणिक) में कोई संदेह नहीं है कि समान सुविधाएं हैं, और आप अपने उद्देश्यों के लिए इनका मूल्यांकन करना चाह सकते हैं। मैं केवल पर्ल पर चर्चा करता हूं क्योंकि मैं जिस भाषा का उपयोग करता हूं और उससे परिचित हूं।


वैसे, मैं बहुत सारे पर्ल खुद लिखता हूं, लेकिन कभी-कभी टूल मेरे लिए चुना जाता है, मेरे द्वारा नहीं :)

-3

यदि आपके सोलारिस पर पर्ल है, तो इसका उपयोग करें। अन्यथा, lk के साथ awk आपका अगला सर्वश्रेष्ठ दांव है, क्योंकि आपके पास स्टेट नहीं है या आपका खोज GNU नहीं है।


-3

मेरे द्वारा उपयोग की गई सोलारिस में एक चाल है, यदि आप एक से अधिक फ़ाइल का आकार पूछते हैं, तो यह कुल आकार को बिना किसी नाम के लौटाता है - इसलिए दूसरी फ़ाइल के रूप में / dev / null जैसी खाली फ़ाइल शामिल करें:

उदा। fileyouwant / dev / null कमांड

मैं यह याद नहीं रख सकता कि यह किस आकार के कमांड ls / wc / etc के लिए काम करता है - दुर्भाग्य से मेरे पास इसका परीक्षण करने के लिए सोलारिस बॉक्स नहीं है।


-4

लिनक्स पर आप du -h $FILEसोलारिस पर भी काम कर सकते हैं?


1
दरअसल, इकाइयों को परिवर्तित किया जा सकता है, लेकिन यह फ़ाइल डेटा आकार ("स्पष्ट आकार") के बजाय डिस्क उपयोग दिखाता है।
पालेक

-7

क्या आपने डु -क्स की कोशिश की | awk '{प्रिंट $ 1 * 1024}'। यह सिर्फ काम हो सकता है।


1
यह फ़ाइल डेटा आकार ("स्पष्ट आकार") के बजाय डिस्क उपयोग दिखाता है।
पालेक
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.