If I run the command du -ah | sort -nr is it possible to make it show which line in the output is a file and which folder? Something like the command ls -l shows which is file and folder with d and - in front.
- 207,228
- 377
2 Answers
It is sort of possible, but not without aid of another command. Specifically, here we're using GNU awk ( that's important, so check your awk version )
$ du -ah | sort -nr | awk '{usage=$1; $1="";cmd="file "$0;cmd |& getline type;print usage,type ;close(cmd)}'
24K .: directory
4.0K ./testdir: directory
4.0K ./out.txt: ASCII text
4.0K ./3.txt: ASCII text
4.0K ./2.txt: ASCII text
4.0K ./1.txt: ASCII text
Of course this approach is slightly flawed since it seems to fail with filenames that contain spaces (still working on improving it )
As alternative, we can also use find command to find all the files and run file and du commands to do our bidding via -exec flag, but that looks slightly ugly (see the edit history). We could, however, use find's -printf flag to print filetype with %y format for much prettier output.
$ find -mindepth 1 -printf "%y\t" -exec du "{}" \; | sort -rn
f 4 ./out.txt
f 4 ./3.txt
f 4 ./2.txt
f 4 ./1.txt
f 0 ./with space.txt
d 4 ./testdir
Obviously here f is for regular file and d is for directory. See find's manual for more info on flags and filetype letters
- 107,582
As Serg says, du can't do this by itself. To process filenames safely, the best way is to separate them with the ASCII nul character (\0), and du can do that. So, using that, along with sort and xargs' ability to handle null-delimited input:
du -0ah |
sort -zh |
xargs -0 sh -c 'for i; do s=${i%%[[:space:]]*};f=${i#*[[:space:]]}; echo "$s" "$(ls --color -dF "$f")"; done' _
The -0, -z and -0 options tell du, sort and xargs to use ASCII nul as the separator.
Then, s=${i%[[:space:]]*} to get the start of the line until whitespace (which is the size), and f=${i#*[[:space:]]} to get everything else (the filename). Then we get ls to print the filename with decoration.
Example:
$ du -0ah Screenshots | sort -zh | xargs -0 sh -c 'for i; do s=${i%%[[:space:]]*};f=${i#*[[:space:]]}; echo "$s" "$(ls --color -dF "$f")"; done' _
512 Screenshots/desktop.ini*
264K Screenshots/Screenshot (1).png*
269K Screenshots/
Because I used ls --color, I also get nice colour output:
- 207,228
