1834935 Members
2148 Online
110071 Solutions
New Discussion

ll file sizes challenge

 
SOLVED
Go to solution
Bill McNAMARA_1
Honored Contributor

ll file sizes challenge

Hi all,

Was wondering if anyone would be up to the challenge of writing a script that could parse an ll result and take options -M -K -G to display file size in meg gig etc..

Thats all!
Reward as usual!

Later,
Bill "Broken calculator"
It works for me (tm)
7 REPLIES 7
Andreas Voss
Honored Contributor
Solution

Re: ll file sizes challenge

Hi,

here my little quick and dirty script:

#!/bin/sh

LANG=C
DIV=1
FMT="%.0f"
for arg
do
case $arg in
-K) DIV=1024; FMT="%8.2fK" ;;
-M) DIV=1048576; FMT="%8.3fM" ;;
-G) DIV=1073741824; FMT="8.3fG";;
esac
done
ls -l $* |awk -vdiv=$DIV -vfmt=$FMT '{
printf("%-11s %2s %-10s %-8s ",$1,$2,$3,$4);
printf(fmt " ", int($5)/div);
printf("%s " , $6);
printf("%2s" , $7);
printf(" %5s" , $8);
for(i=9; i printf("%s ", $(i));
printf(" %s\n", $NF);
}'

Regards
Steve Steel
Honored Contributor

Re: ll file sizes challenge

Hi

Nice script ANDREAS

I fixed it a little

#!/bin/sh

LANG=C
div=1
FMT="%.0f"
for arg
do
case $arg in
-K) div=1024; FMT="%8.2fK" ; shift 1 ;;
-M) div=1048576; FMT="%8.3fM" ; shift 1 ;;
-G) div=1073741824; FMT="%8.3fG" ; shift 1;;
esac
done
echo $*
ls -l $*|tail -n +2 |awk -vdiv=$div -vfmt=$FMT '{
printf("%-11s %2s %-10s %-8s ",$1,$2,$3,$4);
printf(fmt " ", int($5)/div);
printf("%s " , $6);
printf("%2s" , $7);
printf(" %5s" , $8);
for(i=9; iprintf("%s ", $(i));
printf(" %s\n", $NF);
}'


Steve Steel
If you want truly to understand something, try to change it. (Kurt Lewin)
Bill Hassell
Honored Contributor

Re: ll file sizes challenge

Here's my cut:

#!/usr/bin/sh
#
# EZ long-listing of files
#
#
set -u
export PATH=/usr/bin

typeset -L10 PERM
typeset -L3 LNK
typeset -L9 OWNER
typeset -L9 GROUP
typeset -R5 FINAL
typeset -L2 SUFFIX

# Fancy incantation to handle all possible $@ values

ll ${@+"$@"} | while read PERM LNK OWNER GROUP SIZE RESTOFLINE
do
if [ $PERM != total ]
then
if [ $SIZE -lt 1000 ]
then
FINAL=$SIZE
SUFFIX="b"
fi
if [ $SIZE -ge 1000 ]
then
FINAL=$(( SIZE / 1000 ))
SUFFIX="Kb"
fi
if [ $SIZE -ge 1000000 ]
then
FINAL=$(( SIZE / 1000000 ))
SUFFIX="Mb"
fi
if [ $SIZE -ge 1000000000 ]
then
FINAL=$(( SIZE / 1000000000 ))
SUFFIX="Gb"
fi
echo "$PERM $LNK $OWNER $GROUP $FINAL $SUFFIX $RESTOFLINE"
fi
done

-----

Now if you change the ll line from:

ll ${@+"$@"} | while read PERM LNK OWNER GROUP SIZE RESTOFLINE

to:

ll ${@+"$@"} | sort -rnk5 | while read PERM LNK OWNER GROUP SIZE RESTOFLINE

then the script will show files sorted by size. You can also sort by size as a 1-liner with:

ll | sort -rnk5 | more


Bill Hassell, sysadmin
V. V. Ravi Kumar_1
Respected Contributor

Re: ll file sizes challenge

hi,

i tried a shell script.
-----------------------
#!/usr/bin/sh
if [ $1 = "-K" ]
then
ll |awk '{print $1," "$2,$3,"\t"$4,"\t"$5/1024,$6,$7,$8,$9}'
else
if [ $1 = '-M' ]
then
ll |awk '{print $1," "$2,$3,"\t"$4,"\t"$5/1048568,$6,$7,$8,$9}'
else
if [ $1 = '-G' ]
then
ll |awk '{print $1," "$2,$3,"\t"$4,"\t"$5/1073741824,$6,$7,$8,$9}'
fi
fi
fi
--------------------------
usage sh <script name> (-K or -M or -G)
but output is not as clear as ll and for single file or selective files it won't work.

regds

Never Say No
Bill McNAMARA_1
Honored Contributor

Re: ll file sizes challenge

Cool scripts!
Thanks guys!

Bill
It works for me (tm)
Volker Borowski
Honored Contributor

Re: ll file sizes challenge

Hi,
I could not resist, to combine some stuff I learned from the previous three answers to a new variant.
No options needed, just save Script as "lG" and do hardlink to 'lK' and 'lM'.
Use embedded awk-variable CONVFMT to avoid sprintf and turn $5 into an expression by dividing through "div".
Pass standard wildcards or Sort options and have no functional change like "lK -rt".

#!/bin/sh
[[ `basename $0` = 'lG' ]] && div=1000000000
[[ `basename $0` = 'lM' ]] && div=1000000
[[ `basename $0` = 'lK' ]] && div=1000
fmt=`basename $0 | cut -c2`
ll $* | awk -vdiv=$div -vCONVFMT='%8.2f'$fmt '{ print $1 "\t" $2 "\t" $3 "\t" $4 "\t" $5/div "\t" $6 "\t" $7 "\t" $8 "\t" $9 }'

Have fun
Volker
Daimian Woznick
Trusted Contributor

Re: ll file sizes challenge

Bill,

I know this isn;t what you asked for. If we had access to the source code for ls we could implement our own little changes in there. I was looking at the source for FreeBSD (or OpenBSD, can't remember) and saw the following (sorry for the formatting if it doesn't come out right):

while ((ch = getopt(argc, argv, "1ACFLRSTWacdfgiklmnopqrstux")) != -1) {
switch (ch) {
/*
* The -1, -C and -l, -m and -x options all override each
* other so shell aliasing works right.
*/
case '1':
f_singlecol = 1;
f_column = f_columnacross = f_longform = f_stream = 0;
break;
case 'C':
f_column = 1;
f_longform = f_columnacross = f_singlecol = f_stream = 0
;
break;
case 'l':
f_longform = 1;
f_numericonly = 0;
f_column = f_columnacross = f_singlecol = f_stream = 0;
break;


** We could add the K,M,G as options that would act just like the l option.

Further down in the source you will find:

/* If -l or -s, figure out block size. */
if (f_longform || f_size) {
if (!kflag)
(void)getbsize(&notused, &blocksize);
blocksize /= 512;
}


*** Here we could use div function:

div($bytes, 1024)
div($bytes, 1048576)
div($bytes, 1073741824)


Sorry I couldn't do the real program because I don't have the source but it would have been fairly interesting. I guess this could be an addition to the challenge.