I'm trying to find owners of files on the system that all start with a specific name, for example

[unu@here findtest]$ find . -ls
17295583    0 drwxrwxr-x   2 unu      unu            74 Mar 28 03:14 .
17295584    0 -rw-rw-r--   1 br_asd1  br_asd1         0 Mar 28 03:13 ./test1
17295585    0 -rw-rw-r--   1 br_asd2  br_asd2         0 Mar 28 03:13 ./test2
17295586    0 -rw-rw-r--   1 unu      unu             0 Mar 28 03:13 ./test33
17295587    0 -rw-rw-r--   1 br_bfg1  br_bfg1         0 Mar 28 03:14 ./test11
17295588    0 -rw-rw-r--   1 unu      unu             0 Mar 28 03:14 ./test22

I need find to only get files owned by users whose name starts with "br_".

So what I tried was

[unu@here findtest]$ find . -user "br_*" -ls
find: ‘br_*’ is not the name of a known user

Now a method I found that works is using awk, but I have certain problems with this method and it's not really usable for what I'm trying:

[unu@here findtest]$ find . -ls|awk '{if ($5 ~ "br_"||$6 ~ "br_") print $0}'
17295584    0 -rw-rw-r--   1 br_asd1  br_asd1         0 Mar 28 03:13 ./test1
17295585    0 -rw-rw-r--   1 br_asd2  br_asd2         0 Mar 28 03:13 ./test2
17295587    0 -rw-rw-r--   1 br_bfg1  br_bfg1         0 Mar 28 03:14 ./test11

Is there a way to add wildcards to the -user or -group options of find?

  • With getent passwd get a list of users which match br_.* and build a list like: --user br_asd1 --user br_asd2 --user br_bfg1 for find command.
    – Cyrus
    Mar 28 '19 at 3:33
  • GNU find does not have options to pass wildcards for -user and -group fields. One way would be to use GNU coreutils stat and use the %U quantifier to get the owner name. Do something like for file in *; do [ -f "$file" ] || continue; owner=$(stat -c '%U' "$file"); if [[ "$owner" =~ ^br.* ]]; then echo "$file"; fi; done
    – Inian
    Mar 28 '19 at 3:52

If you're writing for bash you can use an array to hold the set of users and another array to generate the corresponding syntax for find to match those users:


# The beginning of the userids we need to match

# Find the matching set of users
    getent passwd |
    awk -F: -vm="$match" 'BEGIN { re = "^" m } $1 ~ re {print $1}'

# Build the list of users ("find ( -user XX -o -user YY -o user ZZ ) ...")
for user in "${users[@]}"
    finds+=('-o' '-user' "$user")
[[ ${#finds[@]} -gt 0 ]] && finds=('(' "${finds[@]:1}" ')')

# Execute the find command with the set of users
find . "${finds[@]}" -ls

As ever, you can prefix the find command with something like echo to see what would be executed. (Or you could run with bash -x to enable line-by-line debug reporting.)

  • Instead of the test in each iteration of that loop, you could just use "${finds[@]:1}" when calling find to ignore that first -o in the list.
    – Kusalananda
    Mar 28 '19 at 8:46

If all you need is just a listing, I would go for a good old grep over find’s output. It would be slower, but much less typing.

At the very basic you might try this, for your example case:

find -printf '%u %p\n' | egrep '^br_'

This gives you the list of files owned by users br_*, shown with username and filename on each line.

You might then expand the output by fiddling the -printf format string.

For instance, to make it resemble more an ls output:

find -printf '%-8.8u %-8.8g %M %8s %t %p\n' | egrep '^br_'

The important thing to keep the command line as short as possible is to place the username at the very beginning, so that the egrep’s part can be kept short like that.

To see all that you can specify in the format string, go here, then search for -printf format.

Be careful though that if your files have newlines in their names then this solution might have problems in showing them.

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.