0

I want to find all files the are not owned by me (that is, having no permission to modify it). I have tried

find . -exec if [[ ! -O {} ]]; then echo {}; fi ;

But if I put the whole command after -exec in quotes, like this:

find . -exec 'if [[ ! -O {} ]]; then echo {}; fi' \;

Neither that work, because the reference to the current file {} is in quotes and therefor does not expand to the file.

The problem is, I do not know how to embed the {} as current file to more complex -exec then simply for example find . -exec grep smf {} \; (that uses the {} only once). How to use -exec option in find in commands, where you reference to the current file more then once ? (That is using {} more time).

Herdsman
  • 340

1 Answers1

2

Your code does not work because the utility that you ask find to run, if, does not exist (it's a keyword in the shell syntax).

The -O test is true if the argument is a file that is owned by the current user. The same test can be done in find itself with -user "$USER" (assuming $USER expands to the current user):

find . -type f ! -user "$USER"

You could also use test -O if your external test utility supports that non-standard test (check man test):

find . -type f ! -exec test -O {} \; -print

If you still wanted or needed to use the -O test built into the bash shell, then you would have to spawn a bash shell to perform the test:

find . -type f -exec bash -c '[[ ! -O "$1" ]]' bash {} \; -print

This starts one inline bash -c script for each found file that runs the test on its first argument ($1). The argument is passed on the command line of the script by find (the bash string before {} will be placed in $0 inside the script, and will be used by that shell for error messages). If the test is true (the file is not owned by you), -print takes effect and prints the pathname of the file.

You can do this a bit more efficiently with

find . -type f -exec bash -c '
    for pathname do
        [[ ! -O "$pathname" ]] && printf "%s\n" "$pathname"
    done' bash {} +

This is more efficient since it passes batches of found pathnames to the bash -c script.

... but using -user "$USER" would be the better option.

See also:

Kusalananda
  • 333,661
  • Can you more elaborate the latter example? Why is there second spawn of bash for {}? – Herdsman Apr 13 '20 at 12:30
  • 2
    @Herdsman There is not. The bash just before {} is a string that is placed in $0. It is only used by the bash -c script if it needs to print any error messages. – Kusalananda Apr 13 '20 at 12:33