Search code examples
bashunixawksolarisls

AWK Command print size in mb,kb or gb by finding a file using ls -l


I want to get a file size using find command along with size in kb, mb or gb with decimal point of two only.

Desired output:

15.04 MB
10MB
10GB

I have tried below command but getting error:

find /orabackup/EXPDP/ATRUS001 -name "expdp_ATRUS001_04122017_0500.dmp" -exec ls -ltr  {} \;  | awk ' {s+=$5}' '{ split( "B KB MB GB TB PB" , v ); s=1; while( $1>1024 ){ $1/=1024; s++ } printf "%.2f %s", $1, v[s] }'

Output:

awk: cmd. line:1: fatal: cannot open file `{ split( "B KB MB GB TB PB" , v ); s=1; while( $1>1024 ){ $1/=1024; s++ } printf "%.2f %s", $1, v[s] }' for reading (No such file or directory

even though file is present in directory giving me above error. Thank you for your help.


Solution

  • awk ' {s+=$5}' '{ split( "B... ?
    

    Why have you split the awk program into two arguments? This is almost certainly what's causing your problem.

    It treats the first argument as the awk program and the second as the input file. This is supported by your error message, stating "cannot open file '{ split ...". What you need to do is to provide the awk program as a single argument.


    As an aside (though I'm not sure about Solaris), many of the GNU utilities sport a -h option to produce human-readable sizes. Have you tried ls -h at all?

    According to the Oracle docs, Solaris supports this, though it may not give you the two decimal places you desire.


    As another aside, I cannot understand why you're trying to add the file size to s for each line if you're interested in individual sizes. I also can't understand why you're using $1 for the divisions when this would be the drwxr-xr-x part of the ls output.

    Perhaps you would be better off specifying in more detail what you want to achieve.

    The best I can do for now is to provide this as an example:

    pax> find . -name '[a-z]*' -exec ls -ltr {} ';' | awk 'BEGIN{split("B KB MB GB TB PB EB ZB YB",v)} {s=1;while($5>1024&&s<9){$5/=1024;s++}printf "%6.2f %-2s %s\n",$5,v[s],$9}'
    154.00 B  ./etc_ntp.conf
    150.00 B  ./input.txt
      1.85 KB ./qq.sh
    200.00 B  ./tmp00
    

    That seems to be basically what you're trying to do though you'll need to modify the find arguments for your specific case (I just grabbed all files starting with a lower-case letter).

    It also limits s so that you don't run off the end of the array if you have Exabyte-sized files :-)

    Breaking it down for readability:

    BEGIN {
        # Only need do this once, allow for bigger files.
        split("B KB MB GB TB PB EB ZB YB", v)
    }
    {
        # Select B suffix.
        s=1
    
        # Need higher suffix, but stop at YB.
        while ($5 > 1024 && s < 9)
        {
            # Divide by 1K, go to next suffix.
            $5 /= 1024
            s++
        }
    
        # Pretty-print the line.
        printf "%6.2f %-2s %s\n", $5, v[s], $9
    }