मैं `wc -l` के साथ एक एकल कुल लाइनें कैसे प्राप्त करूं?


12

मैंने अपने इतिहास में विशिष्ट फाइलों की लाइन काउंट देने के लिए एक git उपनाम जोड़ा है:

[alias]
lines = !lc() { git ls-files -z ${1} | xargs -0 wc -l; }; lc

हालांकि, wc -lकई योगों की रिपोर्टिंग कर रहा है, जैसे कि अगर मेरे पास ~ 100k से अधिक लाइनें हैं, तो यह उनके लिए कुल रिपोर्ट करता है, फिर आगे बढ़ता है। यहाँ एक उदाहरण है:

<100k लाइन्स (वांछित आउटपुट)

$ git lines \*.xslt
  46 packages/NUnit-2.5.10.11092/doc/files/Summary.xslt
 232 packages/NUnit-2.5.10.11092/samples/csharp/_UpgradeReport_Files/UpgradeReport.xslt
 278 total

> 100k लाइनों (पाइप करने के लिए था grep "total")

$ git lines \*.cs | grep "total"
 123569 total
 107700 total
 134796 total
 111411 total
  44600 total

मुझे wc -lउप योगों की एक श्रृंखला नहीं, एक वास्तविक कुल कैसे मिलेगा ?


के अनुसार stackoverflow.com/questions/2501402/... समस्या के साथ है xargs, नहीं wc। मैं अभी भी इसे कैसे ठीक करने में दिलचस्पी रखता हूं, और मुझे उत्तरों में अच्छा समाधान नहीं दिखता है।
एह्रीक

3
क्या आपका संस्करण विकल्प का wcसमर्थन करता --files0-fromहै? फिर आप कर सकते हैं{ git ls-files -z ${1} | wc -l --files0-from=- ; }
मार्क प्लॉटनिक

@MarkPlotnick मुझे लगता है कि जवाब देने के योग्य है।
terdon

नहीं। wc: unrecognized option '--files0-from=-'
एह्रीक

जवाबों:


12

यह कोशिश करो, और स्पष्ट होने के लिए माफी:

cat *.cs | wc -l

या, गिट के साथ:

git ls-files -z ${1} | xargs -0 cat | wc -l

यदि आप वास्तव में आउटपुट को आउटपुट की तरह देखना चाहते wcहैं, तो दोनों अलग-अलग गणनाओं और योगों के साथ, आप awkअलग-अलग लाइनों को जोड़ने के लिए उपयोग कर सकते हैं :

git ls-files -z ${1} | xargs -0 wc -l |
awk '/^[[:space:]]*[[:digit:]]+[[:space:]]+total$/{next}
     {total+=$1;print}
     END {print total,"total"}'

wcमामले में यह अच्छी तरह से नहीं किया जाएगा जैसा कि आपके लिए मायने रखता है। ऐसा करने के लिए, आपको पूरे इनपुट को पढ़ना होगा और इसे सहेजना होगा, कुल की गणना करना होगा, और फिर याद की गई लाइनों के स्वरूपित आउटपुट को प्रिंट करने के लिए उस फ़ील्ड की चौड़ाई का उपयोग करने से पहले फ़ील्ड की चौड़ाई की गणना करने के लिए कुल का उपयोग करना होगा। घर के नवीकरण परियोजनाओं की तरह, awkस्क्रिप्ट कभी भी समाप्त नहीं होती हैं।

(उत्साही संपादकों पर ध्यान दें: पहली awkस्थिति में नियमित अभिव्यक्ति के मामले में एक फाइल है जिसका नाम "कुल और एक स्थान से शुरू होता है; अन्यथा, स्थिति बहुत सरल हो सकती थी $2 == "total"।"


यह काम करता है, लेकिन यह केवल कुल ( git ls-files -z ${1} | xargs -0 cat | wc -l) का उत्पादन करता है। हालाँकि, मैं प्रति-फ़ाइल लाइन काउंट को याद कर रहा हूं जो wc -l ऊपर दिए गए मेरे पहले उदाहरण की तरह प्रदान करता है। यहाँ दोनों दुनिया का सबसे अच्छा पाने का कोई तरीका?
एह्रीक

या, अगर यह बहुत मुश्किल है, तो एक स्विच के बारे में ऐसा कैसे है कि अगर यह इसे तोड़ देगा: बस कुल दें, यदि यह नहीं होगा, तो कुल आउटपुट के साथ सामान्य डब्ल्यूसी प्रति-फ़ाइल दें?
एह्रीक

@Ehryk: आप इसे दो बार कर सकते हैं, एक बार जिस तरह से आप इसे कर रहे थे grep -vकुल पंक्तियों को छोड़ने के लिए, और एक बार जिस तरह से मैं कुल कुल प्राप्त करने का सुझाव देता हूं। या आप संपादित उत्तर में
अजीब

+1: "होम रेनोवेशन प्रोजेक्ट्स की तरह, awk स्क्रिप्ट्स कभी भी वास्तव में समाप्त नहीं होती हैं।"
एह्रीक

उसने जादू की तरह काम किया। मेरा अंतिम परिणाम:git ls-files -z ${1} | xargs -0 wc -l | awk '/^[[:space:]]*[[:digit:]]+[[:space:]]+total$/{next} {total+=$1;print} END {print "\n Total:",total,"lines"}'
एहिर्क

7

यदि आप लिनक्स चला रहे हैं, तो wcसंभवतः आपका GNU कोरुटिल्स से आता है और --files0-fromएक फाइल (या स्टडिन) को पढ़ने का विकल्प होता है जिसमें गिनती करने के लिए फ़ाइल के मनमाने ढंग से लंबे नामों की लंबी सूची होती है। GNU coreutils WC प्रलेखन कहते हैं, "यह उपयोगी है जब फ़ाइल नामों की सूची इतनी लंबी है कि यह एक कमांड लाइन की लंबाई सीमा से अधिक हो सकता है। ऐसे मामलों में, चल xargs के माध्यम से WC अवांछनीय है, क्योंकि यह टुकड़ों में सूची विभाजन और WC प्रिंट बनाता है पूरी सूची के बजाय प्रत्येक सबलिस्ट के लिए कुल। "

तो यह प्रयास करें:

lc() { git ls-files -z ${1} | wc -l --files0-from=- ; } 

संपादित करें: चूंकि आपका wcअंतिम सहस्राब्दी से है और आपके पास वह विकल्प नहीं है, इसलिए यहां एक अधिक पोर्टेबल समाधान है, यह मानते हुए कि आपके पास awk"कुल" नाम की कोई फाइल नहीं है। यह wcकिसी भी totalलाइनों को छोड़, के आउटपुट को फ़िल्टर करेगा और इसके बजाय उन्हें संक्षेप में प्रस्तुत करेगा और अंत में भव्य कुल प्रिंट करेगा।

एक बात मुझे पता नहीं है कि क्या gitउर्फ कार्यान्वयन में एकल कोट्स के अंदर $1और $2अंदर की समस्याएं होंगी , जिन्हें अपरिवर्तित करने की आवश्यकता है awk

lc() {
  git ls-files -z ${1} |
  xargs -0 wc -l |
  awk 'BEGIN { total=0; } { if (NF==2 && $2 == "total") total += $1; else print; } END { print total, "total"; }' ;
}

मैं linux नहीं चला रहा हूँ, यह Windows msysgit.github.io (msysgit) के लिए Git बैश प्रॉम्प्ट में है ।
एह्रीक

ठीक। तो xargsऔर wcआप चल रहे हैं Cygwin से? आप के उत्पादन पेस्ट कर सकते हैं wc --version?
मार्क प्लॉटनिक

वे एक पूर्ण $ wc --version wc (GNU textutils) 2.0 Written by Paul Rubin and David MacKenzie. Copyright (C) 1999 Free Software Foundation, Inc. This is free software; see the source for copying conditions. There is NO warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
साइबर

यह विंडोज़ निष्पादन योग्य पर पूर्ण है,C:\Program Files (x86)\Git\bin\wc.exe
एह्रीक

@Ehryk Msysgit लिनक्स उपकरणों का एक बंदरगाह है, लेकिन इसमें पुराने संस्करण हैं, इसलिए यह नहीं हो सकता है --files0-from
गाइल्स का SO- बुराई पर रोक '31

4

समस्या यह xargsहै कि कमांड को कई रनों में विभाजित किया जा रहा है, इसलिए wcहर बार कुल रिपोर्ट कर रहा है। आपके पास कुछ विकल्प हैं, आप चीजों को जिस तरह से रख सकते हैं और wcआउटपुट को पार्स कर सकते हैं:

git ls-files -z ${1} | xargs -0 wc -l | awk '/total/{k+=$1}END{print k,"total"}';

आप फ़ाइलें बिल्ली कर सकते हैं:

git ls-files -z ${1} | xargs -0 cat | wc -l

या आप xargsपूरी तरह से छोड़ सकते हैं ( यहाँ से अनुकूलित ):

unset files i; while IFS= read -r -d $'\0' name; do 
 files[i++]="$name"; 
done < <(git ls-files -z ${1} ) && wc -l "${files[@]}"

यदि आपकी फ़ाइलों की सूची ARG_MAX से अधिक है, तो यह टूट जाएगी ।


हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.