220

I'm looking to recursively look through directories to find files NOT owned by a particular user and I am not sure how to write this.

RhythmInk
  • 513
  • 1
  • 4
  • 18
mike628
  • 45,873
  • 18
  • 40
  • 57

5 Answers5

334

The find(1) utility has primaries that can be negated ("reversed") using the "!" operator. On the prompt one must however escape the negation with a backslash as it is a shell metacharacter. Result:

find . \! -user foo -print
Mel
  • 6,077
  • 1
  • 15
  • 12
  • 11
    escaping the `!` seems to be optional – doub1ejack Jan 23 '14 at 15:17
  • piping the output to `xargs ls -al` can provide more info than the `-print` flag – doub1ejack Jan 23 '14 at 15:18
  • 2
    piping the output to `xargs -I{} -P3 -- ${cmdhere} {}` can have ${cmdhere} operate on each file in parallel. cmdhere ::= standard unix utils; standard unix utils ::= chmod, chown, stat, ls, ... – Dwight Spencer Mar 04 '14 at 07:12
  • 1
    @sorin do you mean the `find . ...` or piping to `xargs` the first or second way? – Kev Jul 16 '14 at 16:55
  • 5
    find has the -exec flag -> `find . ! -user foo -exec chown : {} \;` – pastephens Feb 12 '15 at 15:06
  • xargs can provide a significant performance boost .v. -exec, since chown can take a list of many files to chown on the same command like, saving the cost of many execs. – Funcan Apr 20 '16 at 10:49
  • 1
    how to add owner info as output? – Duc Tran Aug 05 '16 at 17:01
  • I used `-not` to avoid escaping the `!` but apparently it isn't POSIX compliant. From the man page: `-not expr Same as ! expr, but not POSIX compliant.`. – marczych Oct 07 '16 at 22:20
  • @Silentbang did you ever figure that out? i would like to know as well – Anthony Aug 30 '17 at 16:42
  • 1
    @Anthony Use printf option to get it along with file name: `find . \! -user foo -printf '%p - %u\n'`. Actually I just found out by reading the 'find' command manual as you reminded me. – Duc Tran Aug 31 '17 at 17:12
  • 1
    thanks! And @Sorin, it does work recursively for me (centos 7 : find /path \! -user myUser) – tisc0 Feb 17 '18 at 22:24
  • 5
    @sorin: The exclamation point must be escaped if Bash history is active (`set -H`) which is usually on by default. – Dennis Williamson Jul 11 '18 at 20:54
46

Looking for files NOT owned by someone

Others have answered the question "NOT owned by a particular user" in the body. Here's one that answers the titular question but has not been provided:

$ find / -nouser

You can use it like so:

$ sudo find /var/www -nouser -exec chown root:apache {} \;

And a related one:

$ find / -nogroup
jww
  • 97,681
  • 90
  • 411
  • 885
  • 9
    I'll give you a vote for the technicality, but people would generally say "not owned by anyone" if they meant what you were interpreting. – Shibumi May 21 '18 at 13:26
  • 3
    @Shibumi - Yeah, sounds about right for those splitting hairs. The problem I faced was, I needed to find files literally not owned by any user. It surfaced after a web server refresh and migration. Some user/group ids changed so I needed to script a chown. – jww Jan 03 '19 at 23:08
10

-user finds by user or user ID, and ! inverts the predicate. So, ! -user ....

Ignacio Vazquez-Abrams
  • 776,304
  • 153
  • 1,341
  • 1,358
  • 5
    Downvoted because it doesn't add anything to the accepted answer, and it masks other possible answers (such as the zsh glob pattern below). – Ulysse BN Oct 14 '19 at 09:16
10

You can use this:

find <dir> ! -user <username> 
CrayonViolent
  • 32,111
  • 5
  • 56
  • 79
  • 6
    Downvoted because it doesn't add anything to the accepted answer, and it masks other possible answers (such as the zsh glob pattern below). – Ulysse BN Oct 14 '19 at 09:16
  • 1
    This answer was given 3 minutes after the accepted answer. People deserve credit for giving answers and they are not psychic. – Dino Dini May 28 '23 at 15:32
6

Using z-shell (zsh) you can use

ls -laR *(^U)

or

ls -la **/*(^U)

to search for all files recursively not owned by you.

A.B.
  • 460
  • 5
  • 18
  • It is true that the command above will not list dot files, even with the `-a` flag because of the wildcard expansion. To catch dot files use the zsh `dotglob` option: `setopt dotglob`. In one line: `(setopt dotglob; ls **/*(^U) )`. The parentheses are to run in a subshell so that you don't have to run `setopt nodotglob` after you've finished. – Zorawar Mar 09 '18 at 01:31
  • @Zorawar You can also add `D` to the parenthesis: `ls **/*(D^U)`. – Marc Cornellà Dec 22 '20 at 19:55
  • @MarcCornellà You're right; I did not know that. Thank you. That's a much better option than having to use setopt if it will be a one-time usage. – Zorawar Dec 23 '20 at 22:37