bug-coreutils
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

Re: "sort" utility short comming or bug: cannot sort according to "human


From: Pádraig Brady
Subject: Re: "sort" utility short comming or bug: cannot sort according to "human format" criterion.
Date: Thu, 05 Jan 2006 11:06:02 +0000
User-agent: Mozilla Thunderbird 1.0.7 (X11/20051013)

Pádraig Brady wrote:

>Andre Gompel wrote:
>
>  
>
>>Dear colleague:
>> it looks like a bug... or at least a short comming.
>>
>>If I use the -n or -g option I cannot sort according to the output format of 
>>the "du" or "ls" commands.
>>
>>Example:
>>
>>      du -chs * |sort -n |more
>>
>>I am not sure what would be the best approach, but I would tend to add one 
>>more option (says -h for "human format" compatibility).
>> 
>>
>>    
>>
>I see what you mean, but that would definitely not
>be a stable sort as info is lost in the number -> human conversion.
>You really need to sort before the human conversion.
>Have a look at: http://www.pixelbeat.org/scripts/dutop
>  
>
Actually thinking a bit more about this, a seperate util for
formating numbers for human consumption would be useful.
I threw the attached python prog together as an example.
for the above example you would use it like:

du -cbs * | sort -k1,1n | ./human.py --columns=1 --divisor=1000

Do others think a util like this would a useful addition to coreutils?

cheers,
Pádraig.
#!/usr/bin/env python

#TODO: support ranges for --column option
#TODO: support converting from back from "human" numbers to "standard" numbers
#TODO: support aligning output like `column -t`
#TODO: support --col-delimiters option

import os
import sys
import getopt
def Usage():
    print "Usage: %s [OPTION] [PATH]" % os.path.split(sys.argv[0])[1]
    print "    --divisor=value   The default value is 1 which means insert 
thousands seperator."
    print "                      Other possible values are 1000 and 1024."
    print "    --columns=1,2,3"
    print "    --help            display help"

try:
    lOpts, lArgs = getopt.getopt(sys.argv[1:], "", 
["help","divisor=","columns="])

    if len(lArgs) == 0:
        infile = sys.stdin
    elif len(lArgs) == 1:
        infile = file(lArgs[0])
    else:
        Usage()
        sys.exit(None)

    if ("--help","") in lOpts:
        Usage()
        sys.exit(None)

    divisor=1
    columns=[]
    for opt in lOpts:
        if opt[0] == "--divisor":
            divisor=opt[1]
            if divisor == "1":
                divisor = 1
            elif divisor=="1000" or divisor=="1024":
                divisor = float(divisor)
            else:
                raise getopt.error, "Invalid divisor"
        if opt[0] == "--columns":
            columns=[int(col) for col in opt[1].split(",")]

except getopt.error, msg:
    print msg
    print
    Usage()
    sys.exit(2)

import locale
locale.setlocale(locale.LC_ALL,'')

def human(num, power=" "):
    if divisor == 1:
        return locale.format("%.1f",num,1)
    powers=[" ","K","M","G","T"]
    while num >= 1000:
        num /= divisor
        power=powers[powers.index(power)+1]
        human(num,power)
    return "%6.1f%s" % (num,power)

for line in infile:
    line = line.split()
    column=0
    for str in line:
        column+=1
        if not len(columns) or column in columns:
            try:
                num = float(str)
                str = human(num)
                if str.endswith(".0 "):
                    str = str[:-3]+"   "
                elif str.endswith(".0"):
                    str = str[:-2]
            except:
                pass
        print str,
    print

reply via email to

[Prev in Thread] Current Thread [Next in Thread]