How to show a list of files from some directory root sorted in file size descending order from command line?
Ubuntu – Showing file sizes in sorted order
command line
Related Solutions
#!/usr/bin/perl -w
use strict;
unless ( @ARGV == 1 && -f -r $ARGV[0] ) {
die "Expected single file argument!\n";
}
my %cols;
my $ind = 0;
while (<>) {
chomp;
next if /^\s*($|#)/;
( @{ $cols{col1} }[$ind], @{ $cols{col2} }[$ind], @{ $cols{col3} }[$ind] ) = split;
$ind++;
}
my @sorted1 = map { ${ $cols{col1} }[$_] } sort {
${ $cols{col1} }[$a] <=> ${ $cols{col1} }[$b] or
${ $cols{col2} }[$a] <=> ${ $cols{col2} }[$b] or
${ $cols{col3} }[$a] <=> ${ $cols{col3} }[$b]
} keys @{ $cols{col1} };
my @sorted2 = map { ${ $cols{col2} }[$_] } sort {
${ $cols{col1} }[$a] <=> ${ $cols{col1} }[$b] or
${ $cols{col2} }[$a] <=> ${ $cols{col2} }[$b] or
${ $cols{col3} }[$a] <=> ${ $cols{col3} }[$b]
} keys @{ $cols{col2} };
if ( "@sorted1" eq "@{ $cols{col1} }" and "@sorted2" eq "@{ $cols{col2} }") {
print "File is sorted!\n"
}
else { print "File is unsorted!\n" };
__END__
If the columns are:
X1 Y1 Z1
X2 Y2 Z2
Sort will be:
if (x1 > x2) then X1 Y1 Z1
> X2 Y2 Z2
if (X1 == X2) && (Y1 > Y2) then X1 Y1 Z1
> X2 Y2 Z2
To add more columns into the sort order, copy the pattern for the first two. I hope that's what you asked for.
Basic idea
One could emulate the ls -l
with find. For instance, like with find
command that will run du
per each directory and file found:
find . -maxdepth 1 ! -name "." -printf "%M %u %g " -exec du -sh {} \; 2> /dev/null
Sample output ( side note , here I am using -type d
to show listing for directories only for demo purpose; this command without -type d
will list all files and directories):
DIR:/xieerqi
skolodya@ubuntu:$ find . -maxdepth 1 -type d ! -name "." -printf "%M %u %g " -exec du -sh {} \; 2> /dev/null | head
drwxrwxr-x xieerqi xieerqi 348K ./addRemoveDistribution
drwxr-xr-x xieerqi xieerqi 2.2G ./Downloads
drwxrwxr-x xieerqi xieerqi 4.0K ./.screenlayout
drwxr-xr-x xieerqi xieerqi 4.0K ./Public
drwxrwxr-x xieerqi xieerqi 28K ./Youku Files
drwxrwxr-x xieerqi xieerqi 142M ./.minecraft
drwx------ xieerqi xieerqi 20K ./.gnupg
drwxrwxr-x xieerqi xieerqi 2.5G ./.Genymobile
drwxrwxr-x xieerqi xieerqi 73M ./genymotion
drwxrwxr-x xieerqi xieerqi 104K ./scripts
NOTE: find
has -ls
flag, which I am not using here, for the same reason as OP stated - it shows canonical 4096 bytes
Simplification
This command itself can be turned into an alias, something like ls2
or a function, which then also could take $1
argument. For instance, here's what I've placed into my .bashrc
and how it works:
function lscwd
{
# Function to stat files and folders in current dir
# Takes first argument as directory to stat
# If no directory supplied, current dir assumed
if [ -z "$1" ];then
DIR="."
else
DIR="$1"
fi
find "$DIR" -maxdepth 1 ! -name "." -printf "%M %u %g " -exec du -sh {} \; 2> /dev/null
}
Sample runs:
DIR:/xieerqi
skolodya@ubuntu:$ lsc
lscpu lscwd
skolodya@ubuntu:$ lscwd | head
drwxrwxr-x xieerqi xieerqi 348K ./addRemoveDistribution
drwxr-xr-x xieerqi xieerqi 2.2G ./Downloads
drwxrwxr-x xieerqi xieerqi 4.0K ./.screenlayout
drwxr-xr-x xieerqi xieerqi 4.0K ./Public
drwxrwxr-x xieerqi xieerqi 28K ./Youku Files
drwxrwxr-x xieerqi xieerqi 142M ./.minecraft
drwx------ xieerqi xieerqi 20K ./.gnupg
drwxrwxr-x xieerqi xieerqi 2.5G ./.Genymobile
drwxrwxr-x xieerqi xieerqi 73M ./genymotion
drwxrwxr-x xieerqi xieerqi 104K ./scripts
DIR:/xieerqi
skolodya@ubuntu:$ lscwd /etc | head
drwxr-xr-x root root 18M /etc
drwxr-xr-x root root 68K /etc/logrotate.d
drwxr-xr-x root root 36K /etc/apm
drwxr-xr-x root root 96K /etc/speech-dispatcher
drwxr-xr-x root root 28K /etc/jwm
drwxr-xr-x root root 8.0K /etc/hp
drwxr-xr-x root root 8.0K /etc/gtk-2.0
drwxr-xr-x root root 20K /etc/gtkmathview
drwxr-xr-x root root 68K /etc/xml
drwxr-xr-x root root 8.0K /etc/esound
Output organization
There's no way to colorize the output natively in find
, which is designed specifically to parse filenames. ls
coloring comes from special characters included into the output, which we don't really want.
However, one could read the permissions. The leading -
in -rwxr-xr-x
means it's a regular file, and leading d
in drwxr-xr-x
means directory.
find
also has the handy -type
flag, which we can use as well to filter the output. For instance, here's edited version of lscwd
function lscwd2
{
# Function to stat files and folders in current dir
# Takes first argument as directory to stat
# If no directory supplied, current dir assumed
if [ -z "$1" ];then
DIR="."
else
DIR="$1"
fi
# print directories first
printf "*** DIRECTORIES *** \n"
find "$DIR" -maxdepth 1 -type d ! -name "." -printf "%M %u %g " -exec du -sh {} \; 2> /dev/null
# print non-directories second
printf "*** FILES *** \n"
find "$DIR" -maxdepth 1 ! -type d ! -name "." -printf "%M %u %g " -exec du -sh {} \; 2> /dev/null
}
And sample output:
DIR:/bin
skolodya@ubuntu:$ lscwd2
*** DIRECTORIES ***
drwxrwxr-x xieerqi xieerqi 4.0K ./c
drwxrwxr-x xieerqi xieerqi 12K ./python
drwxrwxr-x xieerqi xieerqi 12K ./perl
drwxrwxr-x xieerqi xieerqi 4.0K ./ANOTHERDIR
drwxrwxr-x xieerqi xieerqi 4.0K ./random
drwxrwxr-x xieerqi xieerqi 108K ./sh
drwxrwxr-x xieerqi xieerqi 38M ./cs2
drwxr-xr-x xieerqi xieerqi 414M ./arduino-1.6.7
drwxrwxr-x xieerqi xieerqi 24K ./codereview
*** FILES ***
-rwxrwxr-x xieerqi xieerqi 4.0K ./preventShutdown.sh
-rw-rw-r-- xieerqi xieerqi 4.0K ./Dimmer.desktop
-rwxrwxr-x xieerqi xieerqi 4.0K ./updateWarning.sh
-rw-rw-r-- xieerqi xieerqi 4.0K ./somefile.txt
-rw-r--r-- xieerqi xieerqi 4.0K ./.bashrc
-rwxr-xr-x xieerqi xieerqi 4.0K ./setup.sh
-rwxrwxr-x xieerqi xieerqi 4.0K ./whiledemo.csh
-rwxr-xr-x xieerqi xieerqi 4.0K ./fmtcode.awk
-rwxrwxr-x xieerqi xieerqi 4.0K ./batmon.sh
-rwxr-xr-x xieerqi xieerqi 4.0K ./Dimmer.sh
-rw-rw-r-- xieerqi xieerqi 4.0K ./somefile2.txt
The output sometimes can be very lengthy , so I would suggest using this function in conjunction with less
paging utility. Just pipe the output like so lscwd2 | less
About ls and stat
Why do people always suggest du
? izx in his brief and awesome answer explained it way better that I could, but in a nutshell, on Unix and Linux everything is a file, and in the reality directory is a file with a list of files linked to it. Thus, stat
and ls
give size of that special file, not the total amount of all the files linked to the directory. But du
is what saves the day. Note what the description in man du
says :
Summarize disk usage of each FILE, recursively for directories.
du
utility jumps down into each directory and sums up file size of each file there. Way different from what ls
and stat
do.
So the purpose of each utility is very different. ls
is doing exactly what it is asked to do - list file sizes, and coming from Windows world we understand directory's size as being this "bag" whose size depends on the amount of apples in it, if I may use it for comparison. Unix is slightly different, yes, but it is realistic. Maybe it doesn't cater to user needs that much, but it makes sense in real, physical sense.
On a side note, block size is by default 4k, but once file grows over 4k, the filesystem will need to allocate more space. For instance, my home folder has 73GB in total size of all files there. What about the block size of the directory ?
DIR:/bin
skolodya@ubuntu:$ ls -ld $HOME
drwxr-xr-x 94 xieerqi xieerqi 16384 Jan 22 07:24 /home/xieerqi/
Best Answer
From your folder:
You can set how deep it can look for files with
-maxdepth
parameter or without it to be recursive.