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.
- 193,181
- 53
- 473
- 722
- 377
- 1
- 4
- 17
-
1I seem not to understand what you try to achieve, the output show both the disk usage of a folder and of each included file. Is this really what you intended? Maybe the --max-depth=N or -hS options are a start? – hasgarion Dec 31 '16 at 09:59
-
@hasgarion `du` command doesn't colorize it's output and doesn't append leading slash to a directory, so it's difficult to distinguish which one is file and which one is a folder in the output. That's what OP is asking about – Sergiy Kolodyazhnyy Dec 31 '16 at 10:11
-
Hi , there. I've posted an answer. I think the last approach with `find` command would be ideal for what you want. Please let me know if that works well for you. – Sergiy Kolodyazhnyy Dec 31 '16 at 10:24
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
- 103,293
- 19
- 273
- 492
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:
- 193,181
- 53
- 473
- 722
-
1How about this instead? `du -0ah . | sort -zh | while read -r -d '' size file; do printf '%s %s\n' "$size" "$(ls --color -dF -- "$file")"; done`. You don't really need an extra `xargs` and `sh`. – gniourf_gniourf Dec 31 '16 at 12:10
-
@gniourf_gniourf of course. `while` is underappreciated. I just default to `xargs`. – muru Dec 31 '16 at 12:12
