I'm trying to sort the output from ls. The order that I'm going for is this:
Everything is sorted alphabetically within these 'sublists'. At the moment I'm using the find command a number of times to find files meeting the criteria above. Following that I pipe the output from find to sort and then pass the entire sorted list to ls:
#!/bin/bash
find1=`find . -maxdepth 1 -name "_*" -type d -printf "%f\n" | sort`
find2=`find . -maxdepth 1 -name "+*" -type d -printf "%f\n" | sort`
find3=`find . -maxdepth 1 -type l -printf "%f\n" | sort`
find4=`find . -maxdepth 1 -name ".*" -type f -printf "%f\n" | sort`
find5=`find . -maxdepth 1 \( ! -name "." \) -name ".*" -type d -printf "%f\n" | sort`
find6=`find . -maxdepth 1 \( ! -name "_*" \) \( ! -name "+*" \) \( ! -name ".*" \) \( ! -type l \) -printf "%f\n"`
find="$find1 $find2 $find3 $find4 $find5 $find6"
ls -dfhlF --color=auto $find
This doesn't handle any names that contain spaces, and overall seems a bit excessive. I'm sure there is a better way to do this. Any ideas?
Will this work for you? It prints the files in the order you specified, but it won't print them in color. In order to do that, you'd need to strip the ANSI codes from the names before pattern-matching them. As it is, it will handle filenames with embedded spaces, but not horribly pathological names, like those with embedded newlines or control characters.
I think the awk
script is fairly self-explanatory, but let me know if you'd like clarification. The BEGIN
line is processed before the ls
output starts, and the END
line is processed after all the output is consumed. The other lines start with an optional condition, followed by a sequence of commands enclosed in curly brackets. The commands are executed on (only) those lines that match the condition.
ls -ahlF --color=none | awk '
BEGIN { name_col = 45 }
{ name = substr($0, name_col) }
name == "" { next }
/^d/ && substr(name, 1, 1) == "_" { under_dirs = under_dirs $0 "\n"; next }
/^d/ && substr(name, 1, 1) == "+" { plus_dirs = plus_dirs $0 "\n"; next }
/^l/ { links = links $0 "\n"; next }
/^[^d]/ && substr(name, 1, 1) == "." { dot_files = dot_files $0 "\n"; next }
/^d/ && substr(name, 1, 1) == "." { dot_dirs = dot_dirs $0 "\n"; next }
{ others = others $0 "\n" }
END { print under_dirs plus_dirs links dot_files dot_dirs others }
'