sort ls output by users
Solution 1
Determining which column the owner name is in from a single ls -l
output without knowing which is which is not possible. You could try to match the entries in each column with the passwd
file, but there is no guarantee that you would not be matching the group column or the filename column both which could only contain names you find in /etc/passwd
.
If you want to go with ls
, you could run the program twice, once as ls -l
and once as ls -g
. The latter drops the owner so by matching lines based on the other information you would be able to determine the owner name without specification. This is however not an exercise I would be happy to do in a bash shell script.
Solution 2
With zsh
, you can define sort orders and use it in globbing qualifiers like:
zmodload zsh/stat
uid() zstat -A REPLY +uid -- $REPLY
... *(no+uid)
(n
for numerical order, o
for order, +uid
to order with the uid
function). The idea is to have a function that takes a filename in $REPLY
and returns something in $REPLY
that zsh
sorts on.
So, for instance with GNU ls
:
ls -ldU -- *(no+uid)
With GNU only tools, the equivalent would be something like:
find . ! -name . -prune -printf '%U\t%p\0' |
sort -zn |
tr '\0\n' '\n\0' |
cut -f2- |
tr '\0\n' '\n\0' |
xargs -r0 ls -ldU
Solution 3
Don't parse ls
: use stat
stat -c "%U %n" -- * | sort
Solution 4
Since the OP doesn't stipulate particular portability requirements (other than for use in Bash), and since parsing ls seems to remain the popular approach, and since the stat
-based solution doesn't seem to handle newlines in filenames any better (who puts newlines in filenames, anyway?), I'm going to throw in my own suggestion for the most elegant solution:
I believe the OP actually had almost the best answer. It just needs to be escaped to prevent unexpected behavior from aliasing (remember, this is a Bash-specific solution):
\ls -l | sort -k 3
18 characters, only requires ls
and sort
, and no loops. Elegant, easy to understand, and reliable.
Also, as Olivier pointed out in his answer, it may be desirable to limit sort
to only the third column, rather than the whole line starting with that column:
\ls -l | sort -k 3,3
I will retract this answer if someone can find me an implementation of ls -l
that doesn't contain the owner in the third column or a way to break this solution that doesn't break solutions given in other answers.
Solution 5
1) Determine which column is the name:
myls='ls -al'
echo '+' > /tmp/MYOWNFILE.$$ #so file will be of size 2, "+" and newline.
zeuser=$( $myls /tmp/MYOWNFILE.$$ | awk -v myname=$(whoami) '{ for (field=1;field<=NF;field++) { if ($field == myname) { print field ; break } } }' )
zesize=$( $myls /tmp/MYOWNFILE.$$ | awk '{ for (field=1;field<=NF;field++) { if ($field == 2) { print field ; break } } }' )
zename=$( $myls /tmp/MYOWNFILE.$$ | awk -v filename=/tmp/MYOWNFILE.$$ '{ for (field=1;field<=NF;field++) { if ($field == filename) { print field ; break } } }' )
rm /tmp/MYOWNFILE.$$
It put in variable zeuser the column showing the username
I also determine zesize=column holding the size, and zename=column holding the filename
I'll put the ls command in a variable, so the lines determining the column are using the actual command used later on (in case you change it and it changes the column(s) listed)
2) use sort to sort on that column:
$myls | sort -k${zeuser},${zeuser} #sort ONLY on column of usernames (see last example for bad alternative)
$myls | sort -k${zeuser},${zeuser} -k${zename},${zename} #sort on user, and then on filename
$myls | sort -k${zeuser},${zeuser} -k${zesize},${zesize}nr #sort on user,
# and then on size
#modifiers: 'n'=order Numerically (and not alphabetically),
# 'r'=Reverse order
$myls | sort -k${zeuser} #sort STARTING FROM user column, which is probably not what you want!
#indeed the next column is probably the group, then the size...
#It will be sorting in a not so usefull way (especially as the
# size will be sorted alphabetically instead of numerically)
Related videos on Youtube
Comments
-
erch over 1 year
On Linux, is there a way to sort
ls
output by users? What I try to achieve is something like this:user_a file1
user_a file2
user_b another_file
user_c this_file
user_c that_file
user_d file3I am aware that a listing like this would also contain file size, permissions etc. – my main concern is the sorting by users. Would be quite handy, wouln't it
So far I found
ls -l | sort -k 3
to sort by column three which [if usingls -l
] contains the file owner [thussort -k 4
to sort by group].BUT what if the file owner isn't in row three? Is there another way to achieve this, independent from the number of the column?
Update: I forgot to mention that I work in BASH and try to stick to it for quite a while from here on so things don't become more complicated.
-
Admin about 11 years
BUT what if the file owner isn't in row three?
where else it can be? -
Admin about 11 years@nylon100: a lot of unixes (and even on the same one, different version of the OS or the
ls
command) will act differently with many commands. It's good to be extra careful about portability, as a simple script here would be dangerous there (ex: if you rely on column 3 to find which files to delete, and it happens it contains something else than the owner's name, you may end up deleting every files you wanted to keep...) -
Admin about 11 years@depquid : of course ^^ But they also could just have an alias, or a function, changing the output (ex: adding the inode in front) ^^ (but you can use "command ls" instead of "ls" in bash to bypass both)
-
-
erch about 11 yearsI forgot to mention that I work in BASH [and updated my question]. I try to stick to it for quite a while from here on so things don't become more complicated. [I love the choices I have with Linux and don't want to be ungrateful, but for a newb all this possibilities can become to much.]
-
erch about 11 years'Matching with the
passwd
file sounds great – but how to achieve this? -
Anthon about 11 years@cellar.dweller if that would work I would do it in my programming language of choice, but with some output you can never be sure which column are the owner names and not filenames or groupnames. That makes the effort futile IMHO. Better start with the
uid
info as I indicated in my comment on your question. -
erch about 11 yearsThere might come a time when I would be able to code in C but for the moment I am lucky to get along witch basic commands and options, but thanks :)
-
Anthon about 11 yearsMost of the C library functions are also available in in some form in Python, Ruby or Perl. Those are somewhat more forgiving than C, to do these kind of things.
-
Stéphane Chazelas about 11 yearsNote that there are several implementations of
stat
. That one is the GNU one. -
Olivier Dulac about 11 yearsthe awk are done for clarity, not tersity... I'm sure a guru out there will propose a much neater/shorter way
-
depquid about 11 yearsI get this error at step #2:
sort: open failed: 4,3: No such file or directory
The value of$zeuser
is3 4
Thezeuser
assignment doesn't handle when the owner and group names are the same? -
Stéphane Chazelas about 11 yearsOn many systems, the group of
~
has the same name as the user name, so,$field
would then be3 4
there. -
Olivier Dulac about 11 years@depquid: I don't understand: my 1) part take care of finding the columns using the myls command. Assign myls=the_command_you'll_actually_use and it will be determining the columns for that actual command (be it alias or anything) and then the sorts will be using those found values.
-
Olivier Dulac about 11 years@depquid: I edited to break as soon as a match occurs (but if you need the group, it will get a bit more difficult, where you'll need to take the last (=1st if only 1 number returned, or 2nd if 2 number returned in case user=group))
-
erch about 11 yearsForgiving is nice for the Pro's who might have overseen something [oopsie!] but did a good job for 99% of what they did OR ended up giving their best trying to give 99%. But then I welcome 'not forgiving' because if IT is based on math there should be 'right' or 'wrong' and as little as possible in between. I accept strict rules as long as they are there to work as properly as one is able to do. Everything else is confusing - especially for Newbs. It might just be me...
-
Drake Clarris about 11 yearsWell it was a quick and dirty solution - so often what I do in linux when tackling a solution like this. I didn't think about the group - A
break
could be added to stop once the first matching field is found (which should be the user), and escaped thels
to avoid alias problems. Still not perfect, but meh, Works on My Machine© -
Lri about 11 yearsOS X's stat uses
-f
instead of-c
and it only supports%u
(UID) and not%U
(username). -
depquid about 11 years
ls -l | sort -k 3
also "Works on My Machine©", but the OP was looking for a solution that was more robust/portable than that. -
depquid about 11 years@LauriRanta
stat -f "%Su %N" -- * | sort
should work on OS X and *BSD. -
depquid about 11 years@Glenn Why is
stat
better in this case? In my tests, it still doesn't handle newlines in filenames well. -
depquid about 11 yearsSorry, I missed the significance of the edit where you added
$myls
. -
Olivier Dulac about 11 years@depquid: no problem ^^ it happens (and I tend to edit a lot, as I throw things out before actually trying them...).
-
Angel Todorov about 11 yearsnewlines in filenames is really a pathological edge case: no line-oriented tools will be able to handle that.
stat
is not really safer here, but it does provide the (apparently) desired output. Also, since it's inherently difficult to parse the filename fromls -l
output, I'm showing a better technique. Stephane's answer demonstrates a safe way using the zero-byte as a delimiter.