यूनिक्स खोल पर संख्याओं का एक स्तंभ जोड़ें


198

फाइलों की एक सूची को देखते हुए files.txt, मैं उनके आकार की एक सूची प्राप्त कर सकता हूं:

cat files.txt | xargs ls -l | cut -c 23-30

जो कुछ इस तरह का उत्पादन करता है:

  151552
  319488
 1536000
  225280

मैं उन सभी नंबरों का कुल कैसे प्राप्त कर सकता हूं ?

जवाबों:


383
... | paste -sd+ - | bc

सबसे छोटा है जो मैंने पाया है ( UNIX कमांड लाइन ब्लॉग से)।

संपादित करें:- पोर्टेबिलिटी के लिए तर्क जोड़ा , धन्यवाद @Dogbert और @Owen।


अच्छा लगा। अंतिम आवश्यकता - सोलारिस पर भी
ओवेन बी

8
alias sum="paste -sd+ - | bc"शेल पूरा करने के लिए जोड़ा गया, धन्यवाद दोस्त
20

. . .| x=$(echo <(cat)); echo $((0+${x// /+}+0))यदि आप हर समय सभी को
मारना

13
@ शेल्फ, बाहर देखो, तुम सिर्फ अतिभारित/usr/bin/sum
qneill

3
खबरदार, bcकुछ सिस्टम पर उपलब्ध नहीं है! awk, दूसरी ओर POSIX अनुपालन के लिए आवश्यक (मेरा मानना ​​है) है।
vktec

154

यहाँ जाता हैं

cat files.txt | xargs ls -l | cut -c 23-30 | 
  awk '{total = total + $1}END{print total}'

34
Awk का उपयोग करना एक अच्छा विचार है, लेकिन क्यों रखें cut? यह एक पूर्वानुमानित कॉलम संख्या है, इसलिए उपयोग करें... | xargs ls -l | awk '{total = total + $5}{END{print total}'
dmckee --- पूर्व-संचालक ने

3
आप निश्चित रूप से सही हैं - बस पहले से ही जो कुछ भी था उसके अंत में संलग्न करना आसान था :-)
ग्रेग रेनॉल्ड्स

2
@ ब्रैकी के उत्तर में एक कोष्ठक बहुत अधिक :)
डॉ। जन-फिलिप गेर्के १०'१३

7
इस एक छोटा सा बनाने के लिए, आप इस्तेमाल कर सकते हैं total+=$1के बजायtotal = total + $1
vktec

10

Ls -l के आउटपुट से फ़ाइल का आकार पाने के लिए कट का उपयोग करने के बजाय , आप सीधे उपयोग कर सकते हैं:

$ cat files.txt | xargs ls -l | awk '{total += $5} END {print "Total:", total, "bytes"}'

अवाक पांचवें स्तंभ के रूप में "$ 5" की व्याख्या करता है। यह ls -l का कॉलम है जो आपको फ़ाइल का आकार देता है।


10

अगर फ़ाइलनाम में स्थान हैं तो बिल्ली काम नहीं करेगी। यहां एक पर्ल वन-लाइनर है।

perl -nle 'chomp; $x+=(stat($_))[7]; END{print $x}' files.txt

8
python3 -c"import os; print(sum(os.path.getsize(f) for f in open('files.txt').read().split()))"

या यदि आप केवल संख्याओं को जोड़ना चाहते हैं, तो इसमें पाइप करें:

python3 -c"import sys; print(sum(int(x) for x in sys.stdin))"

1
... | python -c'import sys; print(sum(int(x) for x in sys.stdin))'जब अजगर 2 इस साल के अंत में गायब हो जाता है।
नामस्रोत

डॉन @ सीप: ~ / दस्तावेज $ बिल्ली कर | python3 -c "import sys; प्रिंट (int (x) के लिए x में sys.stdin))" Traceback (सबसे हाल का कॉल अंतिम): फ़ाइल "<string>", पंक्ति 1, में <मॉड्यूल> फ़ाइल <string> > ", पंक्ति 1, में <genxpr> ValueError: int के लिए अवैध शाब्दिक () आधार 10 के साथ: '\ n'
उज्ज्वल

5

TMTWWTDI : पर्ल का फ़ाइल आकार ऑपरेटर (-s) है

perl -lne '$t+=-s;END{print $t}' files.txt

5

पूरे ls -l और फिर कट के बजाय आपको स्टेट होने पर दोषी माना जाता है । यह ls -l के सटीक प्रारूप के लिए भी असुरक्षित है (यह तब तक काम नहीं करता जब तक मैंने कट के लिए कॉलम संख्या नहीं बदल दी )

इसके अलावा, बिल्ली के बेकार उपयोग को ठीक किया ।

<files.txt  xargs stat -c %s | paste -sd+ - | bc

2
हुह। 32 वर्षों के लिए यूनिक्स का उपयोग कर रहा है, और कभी नहीं पता था कि <infile command(और बेहतर क्रम में) के समान है command <infile
केमिली गौडेय्यून 21

5

यदि आपके पास bc स्थापित नहीं है, तो प्रयास करें

echo $(( $(... | paste -sd+ -) ))

के बजाय

... | paste -sd+ - | bc

$( ) <- कमांड निष्पादित करने का मान लौटाएं

$(( 1+2 )) <- मूल्यांकन किए गए परिणाम लौटाएं

echo <- इसे स्क्रीन पर गूँजें


4

आप निम्न स्क्रिप्ट का उपयोग कर सकते हैं यदि आप बिना किसी स्क्रिप्ट या अन्य दुभाषियों के शेल स्क्रिप्टिंग का उपयोग करना चाहते हैं:

#!/bin/bash

total=0

for number in `cat files.txt | xargs ls -l | cut -c 23-30`; do
   let total=$total+$number
done

echo $total

3

मैं इसके बजाय "du" का उपयोग करूंगा।

$ cat files.txt | xargs du -c | tail -1
4480    total

यदि आप केवल संख्या चाहते हैं:

cat files.txt | xargs du -c | tail -1 | awk '{print $1}'

5
डिस्क का उपयोग! = फ़ाइल का आकार। डु रिपोर्ट डिस्क उपयोग।
0x6adb015

4
मुझे लगता है कि -b स्विच डू मुझे क्या चाहिए।
रिचीहिंडल

@ 0x6adb015 अच्छा ज्ञान। धन्यवाद मुझे महसूस नहीं हुआ।
माइकलजोन

3
यह विशिष्ट कारण के लिए एक उपयोगी उत्तर है कि ओपी को संख्याओं का कॉलम क्यों जोड़ा गया था, लेकिन सामान्य संख्या-जोड़ मामले के लिए, यह कम हो जाता है। (मैं हर समय "डु" का उपयोग करता हूं, लेकिन मैं यहां कमांड-लाइन गणित की तलाश में आया हूं। :-))
माइकल एच।

12
files.txtबड़े होने पर यह काम नहीं करेगा । यदि तर्कों की संख्या xargsकुछ सीमा तक पहुँचती है, तो यह उन्हें कई कॉल करने के लिए तोड़ देता है du। अंत में दिखाया गया कुल duपूरी सूची के लिए केवल अंतिम कॉल के लिए कुल है ।
मैथ्यू साइमन्यू

3

क्ष में:

echo " 0 $(ls -l $(<files.txt) | awk '{print $5}' | tr '\n' '+') 0" | bc

1
cutस्किप करने पर लेने के लिए अच्छा है , लेकिन आप गणित करने के लिए जागने की क्षमता को अनदेखा करते हैं ...
dmckee --- पूर्व-संचालक ने

1

पाइप से गौक:

 cat files.txt | xargs ls -l | cut -c 23-30 | gawk 'BEGIN { sum = 0 } // { sum = sum + $0 } END { print sum }'

1

ये मेरा

cat files.txt | xargs ls -l | cut -c 23-30 | sed -e :a -e '$!N;s/\n/+/;ta' | bc

6
+1 एक बार और सभी के लिए यह साबित करने के लिए कि पर्ल की तुलना में बदसूरत भाषाएं हैं :)
bdonlan

1
#
#       @(#) addup.sh 1.0 90/07/19
#
#       Copyright (C) <heh> SjB, 1990
#       Adds up a column (default=last) of numbers in a file.
#       95/05/16 updated to allow (999) negative style numbers.


case $1 in

-[0-9])

        COLUMN=`echo $1 | tr -d -`

        shift

;;

*)

        COLUMN="NF"

;;

esac

echo "Adding up column .. $COLUMN .. of file(s) .. $*"

nawk  ' OFMT="%.2f"                                       # 1 "%12.2f"

        { x = '$COLUMN'                                   # 2

          neg = index($x, "$")                            # 3

          if (neg > 0) X = gsub("\\$", "", $x)

          neg = index($x, ",")                            # 4

          if (neg > 1) X = gsub(",", "", $x)

          neg = index($x, "(")                            # 8 neg (123 & change

          if (neg > 0) X = gsub("\\(", "", $x)

          if (neg > 0) $x = (-1 * $x)                     # it to "-123.00"

          neg = index($x, "-")                            # 5

          if (neg > 1) $x = (-1 * $x)                     # 6

          t += $x                                         # 7

          print "x is <<<", $x+0, ">>> running balance:", t

        } ' $*


# 1.  set numeric format to eliminate rounding errors
# 1.1 had to reset numeric format from 12.2f to .2f 95/05/16
#     when a computed number is assigned to a variable ( $x = (-1 * $x) )
#     it causes $x to use the OFMT so -1.23 = "________-1.23" vs "-1.23"
#     and that causes my #5 (negative check) to not work correctly because
#     the index returns a number >1 and to the neg neg than becomes a positive
#     this only occurs if the number happened to b a "(" neg number
# 2.  find the field we want to add up (comes from the shell or defaults
#     to the last field "NF") in the file
# 3.  check for a dollar sign ($) in the number - if there get rid of it
#     so we may add it correctly - $12 $1$2 $1$2$ $$1$$2$$ all = 12
# 4.  check for a comma (,) in the number - if there get rid of it so we
#     may add it correctly - 1,2 12, 1,,2 1,,2,, all = 12   (,12=0)
# 5.  check for negative numbers
# 6.  if x is a negative number in the form 999- "make" it a recognized
#     number like -999 - if x is a negative number like -999 already
#     the test fails (y is not >1) and this "true" negative is not made
#     positive
# 7.  accumulate the total
# 8.  if x is a negative number in the form (999) "make it a recognized
#     number like -999
# * Note that a (-9) (neg neg number) returns a postive
# * Mite not work rite with all forms of all numbers using $-,+. etc. *

1

मुझे इस्तेमाल करना अच्छा लगता है ...।

echo "
1
2
3 " | sed -e 's,$, + p,g' | dc 

वे प्रत्येक पंक्ति का योग दिखाएंगे ...

इस स्थिति में आवेदन:

ls -ld $(< file.txt) | awk '{print $5}' | sed -e 's,$, + p,g' | dc 

कुल अंतिम मूल्य है ...


1
cat files.txt | awk '{ total += $1} END {print total}'

आप awk का उपयोग कर सकते हैं ऐसा करने के लिए यह गैर पूर्णांक को भी छोड़ देता है

$ cat files.txt
1
2.3
3.4
ew
1

$ cat files.txt | awk '{ total += $1} END {print total}'
7.7

या आप ls कमांड का उपयोग कर सकते हैं और मानव पठनीय आउटपुट की गणना कर सकते हैं

$ ls -l | awk '{ sum += $5} END  {hum[1024^3]="Gb"; hum[1024^2]="Mb"; hum[1024]="Kb"; for (x=1024^3; x>=1024; x/=1024) { if (sum>=x) { printf "%.2f %s\n",sum/x,hum[x]; break; } } if (sum<1024) print "1kb"; }'
15.69 Mb

$ ls -l *.txt | awk '{ sum += $5} END  {hum[1024^3]="Gb"; hum[1024^2]="Mb"; hum[1024]="Kb"; for (x=1024^3; x>=1024; x/=1024) { if (sum>=x) { printf "%.2f %s\n",sum/x,hum[x]; break; } } if (sum<1024) print "1kb"; }'
2.10 Mb

आपको पाइप की भी आवश्यकता नहीं है: awk '{ total += $1} END {print total}' files.txtजल्दी है
bmv

0

मेरी राय में, इसका सबसे सरल समाधान यूनिक्स कमांड "expr" है:

s=0; 
for i in `cat files.txt | xargs ls -l | cut -c 23-30`
do
   s=`expr $s + $i`
done
echo $s


0
sizes=( $(cat files.txt | xargs ls -l | cut -c 23-30) )
total=$(( $(IFS="+"; echo "${sizes[*]}") ))

या आप उन्हें पढ़ सकते हैं जैसा कि आप आकारों को पढ़ते हैं

declare -i total=0
while read x; total+=x; done < <( cat files.txt | xargs ls -l | cut -c 23-30 )

यदि आप काटने के आकार और ब्लॉकों के बारे में परवाह नहीं करते हैं, तो ठीक है

declare -i total=0
while read s junk; total+=s; done < <( cat files.txt | xargs ls -s )

0

यदि आपके पास R है, तो आप उपयोग कर सकते हैं:

> ... | Rscript -e 'print(sum(scan("stdin")));'
Read 4 items
[1] 2232320

चूंकि मैं आर के साथ सहज हूं, मेरे पास वास्तव में इस तरह की चीजों के लिए कई उपनाम हैं इसलिए मैं bashइस वाक्यविन्यास को याद किए बिना उनका उपयोग कर सकता हूं । उदाहरण के लिए:

alias Rsum=$'Rscript -e \'print(sum(scan("stdin")));\''

जो मुझे करने दो

> ... | Rsum
Read 4 items
[1] 2232320

प्रेरणा: क्या एकल कमांड में संख्याओं की सूची में न्यूनतम, अधिकतम, औसत और औसत प्राप्त करने का एक तरीका है?

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