I am looking for a command that will return the owner of a directory and only that--such as a regex parsing the ls -lat
command or something similar? I want to use the result in another script.
5 Answers
stat
from GNU coreutils can do this:
stat -c '%U' /path/of/file/or/directory
Unfortunately, there are a number of versions of stat
, and there's not a lot of consistency in their syntax. For example, on FreeBSD, it would be
stat -f '%Su' /path/of/file/or/directory
If portability is a concern, you're probably better off using Gilles's suggestion of combining ls
and awk
. It has to start two processes instead of one, but it has the advantage of using only POSIX-standard functionality:
ls -ld /path/of/file/or/directory | awk '{print $3}'
-
2
-
1That assumes GNU stat, which is not the case on older Linux systems (even on newer systems I'd be wary, there might be a different
stat
(a site-wide standard) in/usr/local/bin
or somewhere in the user's home), and is rarely available on other unices. Feb 20, 2011 at 23:18 -
1
stat -c %U
has the advantage of also working with BusyBox, if thestat
command is compiled in. Feb 21, 2011 at 0:23 -
1
-
1Note that ls will print the uid if there's no local user matching the owner (i.e., on a network share), but
stat -c '%U' DIR
will printUNKNOWN
, which is less helpful or more appropriate, depending on how you look at it.– basic6May 14, 2014 at 8:59
Parsing the output of ls
is rarely a good idea, but obtaining the first few fields is an exception, it actually works on all “traditional” unices (it doesn't work on platforms such as some Windows implementations that allow spaces in user names).
ls -ld /path/to/directory | awk 'NR==1 {print $3}'
Another option is to use a stat
command, but the problem with stat
from the shell is that there are multiple commands with different syntax, so stat
in a shell script is unportable (even across Linux installations).
Note that testing whether a given user is the owner is a different proposition.
if [ -n "$(find . -user "$username" -print -prune -o -prune)" ]; then
echo "The current directory is owned by $username."
fi
if [ -n "$(find . -user "$(id -u)" -print -prune -o -prune)" ]; then
echo "The current directory is owned by the current user."
fi
-
There are some caveats with the
ls | awk
approach too unfortunately, as I've noted here. I haven't yet come up with a solution for the, "target file/dir is a symlink with a different name," issue I mentioned in my recent comment.– beporterJul 15, 2014 at 17:16 -
Instead of
find . -user "$username" -print -prune -o -prune
you could just dofind . -maxdepth 0 -user "$username"
Dec 9, 2016 at 12:18 -
@Gilles Is there any reason you use
awk 'NR==1 {print $3}'
instead of justawk '{print $3}'
? I'm not sure why theNR==1
is necessary here. Sep 10, 2019 at 21:08 -
1@HaroldFischer Only in an edge case where the path contains a newline. It's rarely necessary, but never harmful. Sep 10, 2019 at 21:19
-
@Gilles Very good to know!! Just curious, are you aware of an implementation of
ls
where a newline in a path causes the line to be split in two (which I believe is the edge case you are trying to cover)? On GNUls
(newish version), BusyBoxls
and FreeBSDls
a newline is returned as$'\n'
,?
and?
, respectively. Sep 10, 2019 at 21:48
One can also do this with GNU find
:
find "$directoryname" -maxdepth 0 -printf '%u\n'
This isn't portable outside of the GNU system, but I'd be surprised to find a Linux distribution where it doesn't work.
In pure bash you can convert the output of ls
to an array and index into it.
# (lrwxr-xr-x, 1, myuser, staff, 36, Oct, 21, 16:36, /path/to/file)
file_meta=($(ls -ld /path/to/file))
file_owner="${file_meta[2]}" # myuser
It's not as elegant as using stat
, find
, or awk
, but could work in a pinch.