[SOLVED] how to make "ls" display the real size for directories
Linux - NewbieThis Linux forum is for members that are new to Linux.
Just starting out and have a question?
If it is not in the man pages or the how-to's this is the place!
Notices
Welcome to LinuxQuestions.org, a friendly and active Linux Community.
You are currently viewing LQ as a guest. By joining our community you will have the ability to post topics, receive our newsletter, use the advanced search, subscribe to threads and access many other special features. Registration is quick, simple and absolutely free. Join our community today!
Note that registered members see fewer ads, and ContentLink is completely disabled once you log in.
If you have any problems with the registration process or your account login, please contact us. If you need to reset your password, click here.
Having a problem logging in? Please visit this page to clear all LQ-related cookies.
Get a virtual cloud desktop with the Linux distro that you want in less than five minutes with Shells! With over 10 pre-installed distros to choose from, the worry-free installation life is here! Whether you are a digital nomad or just looking for flexibility, Shells can put your Linux machine on the device that you want to use.
Exclusive for LQ members, get up to 45% off per month. Click here for more info.
I don't have any problem with someone conceptualizing a directory as a container. We are humans, and this is how we think, and to know how much stuff is in a container is a useful piece of knowledge (if it weren't we wouldn't have the du command). Thinking of directories as containers makes things easier to visualize and keep track of things in our minds. It may not be the way the file-system actually works, but it is how most people think, and makes perfect sense whether you have hard links or not. To visualize a directory as a database could only be useful if you are someone who is actually designing or programming a file-system. For anyone else, to do so is making things way more complicated than they need to be. If someone knows what the size entry in ls means for a directory entry, then they're fine. But, if they don't, then it needs to be explained, because the natural way of thinking is to assume it means something that it does not. It isn't the conceptualizing that is wrong. It is the assumption that a particular tool is giving one piece of information, when it is actually giving another piece, that is wrong. That is fixed by teaching others how to use our tools.
My 2 pennies,
Forrest
You can conceptualize it any way you want as long as you understand how it really works and that a directory is not really a container. Problems arise when people don't understand this.
I guess this is a bad time to tell you that files don't really have names?
@ colucix
I used your function in the following script:
Code:
#!/bin/bash
#file lsd
#provide disk usage of directories in ls -lh listing
if [ $# -ne 1 ] #if no argument, assign pwd to var a
then
a='./'
else a=$1 #else assign argument to var a
fi
len=${#a} #extract length of a
#count char of a until the last occurrence of "/"
e=`expr match $a '.*/'`
#if count not equal to length of a
#(that is: argument without a final slash)
if [ "$e" -ne "$len" ]
then
a=${a}/ #add slash to argument
fi
#change the 5th field of "ls -lh" with "du -hs"
ls -lh $a | awk -v dir=$a '
substr($1,1,1)=="d"{
("du -hs " dir$NF) | getline size
split(size,size_)
sub($5,size_[1],$5)
}
{ printf "%s %3s %s %s %6s %s %s %s %s\n",$1,$2,$3,$4,$5,$6,$7,$8,$9}'
#print the whole dimension of argument
echo -n "Grand total "; du -sh $a
The script runs well, but symbolic links and directories having long names and some spaces give problems. The link name is truncated after -> and directories name are truncated too. In the latter case the last word of the name become a directory to scan.
In example:
It works well with printf but du -hs scan every word of a directory.
The apostrophe gives this error:
/bin/sh: -c: line 0: unexpected EOF while looking for matching `''
/bin/sh: -c: line 1: syntax error: unexpected end of file
Finally the dimension of following n directories was the same, where n was the number of word of the first directory.
I tried to assign the substr to a variable, example:
Any reason for not downloading the ls source and modifying that to build a variant or add an option?
Reading of ls.c and du.c of coreutils shows me that is not a simple task to modify such a code.
It needs a deep knowledge of C language and filesystem structure that I have not. Till now...
This is one of the reasons. At least for me.
Bye
gross6
Reading of ls.c and du.c of coreutils shows me that is not a simple task to modify such a code.
It needs a deep knowledge of C language and filesystem structure that I have not. Till now...
This is one of the reasons. At least for me.
Bye
gross6
#!/bin/bash
#file lsd
#provide disk usage of directories recursively in ls -lh listing
if [ $# -ne 1 ] #if no argument, assign pwd to var a
then
a='./'
else a=$1 #else assign argument to var a
fi
len=${#a} #extract length of a
#count char of a until the last occurrence of "/"
e=`expr match $a '.*/'`
#if count not equal to length of a
#(that is: argument without a final slash)
if [ "$e" -ne "$len" ]
then
a=${a}/ #add slash to argument
fi
#change the 5th field of "ls -lh" with "du -hs"
ls -lh $a | awk -v dir=$a '
substr($1,1,1)=="d"{
("du -hs "dir$8"*") | getline size
split(size,size_)
sub($5,size_[1],$5)
}
substr($1,1,1)=="t"{
printf ("Files total %s\n",$2)
}
substr($1,1,1)!="t"{
printf ("%s %3s %s %s %6s %s %s %s\n",$1,$2,$3,$4,$5,$6,$7,substr($0,index($0,$8)))
}'
#print the whole dimension of argument
echo -n "Grand total "; du -sh $a
works well with spaces in dir names.
But there are still troubles with apostrophe in dir name, and when the user and/or group name coincides with dir name.
In summary it mostly works.
With links you're getting into the qn of whether the final file's data (or dir) pointed to should be included or not.
After all, in reality, only the link entry is 'inside' the dir being measured. The actual file is 'inside' the other dir where it really lives...
NB: 'inside' because, as above, a dir file (aka inode) is only an index, it does not physically contain the file's (data) listed, which is why you can fill a partition from any dir ie each dir 'area' does not reserve a space for potential files...
#!/bin/bash
#file lsd
#provide disk usage of directories recursively in ls -lh listing
if [ $# -ne 1 ] #if no argument, assign pwd to var a
then
a='./'
else a=$1 #else assign argument to var a
fi
len=${#a} #extract length of a
#count char of a until the last occurrence of "/"
e=`expr "$a" : '.*/'`
#if count not equal to length of a
#(that is: argument without a final slash)
if [ "$e" -ne "$len" ]
then
a=${a}/ #add slash to argument
fi
#change the 5th field of "ls -lh" with "du -hs"
ls -lh "$a" | awk -v dir=$a '
substr($1,1,1)=="d"{
("du -hs "dir$8"*") | getline size
split(size,size_)
sub($5,size_[1],$5)
}
substr($1,1,1)=="t"{
printf ("Files total %s\n",$2)
}
substr($1,1,1)!="t"{
printf ("%s %3s %s %s %6s %s %s %s\n",$1,$2,$3,$4,$5,$6,$7,substr($0,index($0,$8)))
}'
#print the whole dimension of argument
echo -n "Grand total "; du -sh "$a"
#modifications 2011/01/11
# {z=(substr($0,index($0,$8),1)"*")}
# z=`ls -l | awk '{printf "%s:",substr($0,index($0,$8))}'`
# ls -lh | awk '{print substr($0,index($0,$8))}' | sed -e "s/ /\\\ /g"
# ("z=$(`ls -l $a | awk {print substr($0,index($0,$8))}`)")
# ("du -hs "dir$8"* 2>/dev/null") | getline size
# s=`echo $a | sed -e "s/ /\\ /g" -e "s/'/\'/g"`
# ("du -hs $s"$8"*") | getline size
#printf -v s '%q' ${a}
#ls -lh "$a" | awk -v dir="${s}" '
# substr($1,1,1)=="d"{
# ("du -hs "dir$8"*") | getline size
This is my last try... it's a little better than the previous one.
You can see my attempts commented at the bottom of the code but it's difficult for me to find a code that works with spaced dir names listed and spaced name argument of script as well.
Not to mention apostrophes.
#!/bin/bash
#file lsd
#provide disk usage of directories recursively in ls -lh listing
if [ $# -ne 1 ] #if no argument, assign pwd to var a
then
a='./'
else a=$1 #else assign argument to var a
fi
len=${#a} #extract length of a
#count char of a until the last occurrence of "/"
e=`expr "$a" : '.*/'`
#if count not equal to length of a
#(that is: argument without a final slash)
if [ "$e" -ne "$len" ]
then
a=${a}/ #add slash to argument
fi
#change the 5th field of "ls -lh" with "du -hs"
ls -lh "$a" | awk -v dir_arg="${a}" '
BEGIN {
gsub(/ /,"\\ ",dir_arg)
gsub(/'"'"'/,"'"\\\'"'",dir_arg)
}
substr($1,1,1)=="d"{
{
if ($3==$8 || $4==$8)
dir_listed = $8
else
dir_listed = substr($0,index($0,$8))
}
gsub(/ /,"\\ ",dir_listed)
gsub(/'"'"'/,"'"\\\'"'",dir_listed)
("du -hs "dir_arg dir_listed) | getline size
split(size,size_)
sub($5,size_[1],$5)
}
substr($1,1,1)=="t"{
printf ("Files total size %s\n",$2)
}
substr($1,1,1)!="t" && substr($1,1,1)!="d"{
printf ("%s %3s %s %s %5s %s %s %s\n",$1,$2,$3,$4,$5,$6,$7,substr($0,index($0,$8)))
}
substr($1,1,1)=="d"{
printf ("%s %3s %s %s %5s %s %s %s\n",$1,$2,$3,$4,$5,$6,$7,dir_listed)
}
'
#print the whole dimension of argument
echo -n "Grand total size "; du -sh "$a"
#updated 2011/01/14
LinuxQuestions.org is looking for people interested in writing
Editorials, Articles, Reviews, and more. If you'd like to contribute
content, let us know.