63

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.

102

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
    stat -c %U /path, if brevity is a bonus. – tsvallender Feb 20 '11 at 23:18
  • 1
    That 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. – Gilles 'SO- stop being evil' Feb 20 '11 at 23:18
  • 1
    stat -c %U has the advantage of also working with BusyBox, if the stat command is compiled in. – Gilles 'SO- stop being evil' Feb 21 '11 at 0:23
  • 1
    Nice, the last example (ls) works both on Unix/OSX and Linux – kenorb Nov 28 '13 at 15:52
  • 1
    Note 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 print UNKNOWN, which is less helpful or more appropriate, depending on how you look at it. – basic6 May 14 '14 at 8:59
19

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. – beporter Jul 15 '14 at 17:16
  • Instead of find . -user "$username" -print -prune -o -prune you could just do find . -maxdepth 0 -user "$username" – Niklas Holm Dec 9 '16 at 12:18
  • @Gilles Is there any reason you use awk 'NR==1 {print $3}' instead of just awk '{print $3}'? I'm not sure why the NR==1 is necessary here. – Harold Fischer Sep 10 at 21:08
  • 1
    @HaroldFischer Only in an edge case where the path contains a newline. It's rarely necessary, but never harmful. – Gilles 'SO- stop being evil' Sep 10 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 GNU ls (newish version), BusyBox ls and FreeBSD ls a newline is returned as $'\n', ? and ?, respectively. – Harold Fischer Sep 10 at 21:48
9

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.

  • 1
    This works on every non-embedded Linux system and a few others (e.g. Cygwin). Embedded systems are likely to have Busybox, whose find doesn't have -printf. – Gilles 'SO- stop being evil' Feb 21 '11 at 0:22
  • Like I said, GNU system. – mattdm Feb 21 '11 at 1:24
  • Systems without GNU coreutils (such as FreeBSD) doesn't have -printf :-(. – pevik Mar 15 '16 at 21:38
  • @pevik Yeah, like I said, still. But you can install GNU find if you need it. :) – mattdm Mar 15 '16 at 21:44
  • @mattdm: not always :-(. most importantly when you write scripts which should be portable. – pevik Mar 15 '16 at 22:27
2

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.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.