0

In my previous question In find -exec, how to substitue current file by {}?, I have asked about test with find. I want to find all files I do not own. So there is proper find command:

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

but so should be this one as well:

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

yet both gives different results .

1) if I do [command one] | wc -c --> 4121

But: [command two] | wc -c --> 236768 (PS: I am searching files in my $HOME).

Both gives different numbers of how many files they found.

2) Both still give in result files, that are directories (yes, directories I do not own and thus - permission denied). They give directories despite having find . -type f type files (not dirs) in argument of option, why? (When I ls -ld one of those directory, none is link or anything else)

Herdsman
  • 320
  • 4
  • 20
  • Are you running either of these commands with `sudo`? You would definitely get "Permission denied" errors when `find` tries to enter directories not owned by you that you don't have access to. This is most likely why these errors occur. Have you looked at the output (not errors) to try to figure out what the differences in result are? – Kusalananda Apr 13 '20 at 18:41
  • 1) no sudo. That is the point, I am trying to look up only those files I own. I get permission denied after `wc` (or I only see it after `wc`, but the error could arise before pipe by `find`) 2) No I did not look at results, there is many files, that would take a lot of time to compare, neither does `diff` work, because that would be the other way - big output. Is there any program for that? Anyway, why it is showing directories, when specified `type f`? – Herdsman Apr 13 '20 at 18:50
  • It is not clear if "showing directories" means that the error messages mention directories, or if the `find` results mention directories. If you have directories that you don't have access to, I would expect these to show up in error messages. As for comparing, just sort the output and use `diff`. – Kusalananda Apr 13 '20 at 19:00
  • `showing directory` was meant by this `find: ‘./.cpan/build/Class-Load-0.25-0/t’: Permission denied`, this is a directory, that does not belong to me. I would suspect, `find` was trying to open it in order to recursively find files by my previous command (the original one). So it still search for files, not dirs (and thus does not violate the `type f`), but I do not know the inner mechanism of `find` – Herdsman Apr 13 '20 at 19:07
  • 1
    @Herdsman You're right about the origin of that error -- `find` is trying to explore that directory to find files, and getting that error as a result. As for the differences in files listed: rather than trying to catalog them all, I'd just look at the first few differences, and try to figure out *why* they're different. – Gordon Davisson Apr 13 '20 at 19:16
  • 1
    Why are you running `wc -c`? That will count characters, not lines. So it doesn't help you know how many results you got, only how those results were reported. I doubt this is the issue, it just seems strange to use `-c` here. – terdon Apr 13 '20 at 19:20

2 Answers2

1

Hmm ..., in my homedir, both commands work the same. 8-/

Nevertheless, you should redirect the stderr to /dev/null and use wc -l to correctly count the output.

find . -type f ! -user "$USER" 2>/dev/null | wc -l
find . -type f -exec bash -c '
    for pathname do
        [[ ! -O "$pathname" ]] && printf "%s\n" "$pathname"
    done' 2>/dev/null bash {} + | wc -l

From here you could redirect the results to text files and compare the files to look for differences.

find . -type f ! -user "$USER" 2>/dev/null > /tmp/file_1.txt
find . -type f -exec bash -c '
    for pathname do
        [[ ! -O "$pathname" ]] && printf "%s\n" "$pathname"
    done' 2>/dev/null bash {} + >/tmp/file_2.txt
diff /tmp/file_{1,2}.txt

If there are differences, take some of the excess files of /tmp/file_2.txt and investigate further why the file is not considered ' True if file exists and is owned by the effective user id'.

bey0nd
  • 917
  • 3
  • 11
  • It _looks_ like you are trying to redirect the output of the `bash -c` script, but since the placing of the redirection doesn't really matter (redirections are parsed separately) you are actually redirecting the output of `find`, not the `bash -c` script. This happens to be what I think you want to do though. – Kusalananda Apr 13 '20 at 19:28
  • Now you got me thinking again. I wanted to redirect the stderr of `find` as find is most likely throwing the 'permission denied' message. I just got the `bash {} +`mixed up in it. Nevertheless, I curious to see where the additional 232600 characters are coming from. ;-) – bey0nd Apr 13 '20 at 19:39
  • In a now deleted self-answer, they indicate that the lower of the numbers is in fact coming from `wc -l`. – Kusalananda Apr 13 '20 at 19:40
  • 236768 characters divided by 4121 lines ~ 57 char/line. That sounds reasonable. – bey0nd Apr 13 '20 at 19:46
0

To avoid having find enter directories that are not actually accessible to you, you can use ! -executable -prune:

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

The negated -executable test will be true for directories that you don't have access to, and -prune will remove these from find's search tree, stopping the utility from trying to access them, and thus avoiding generating permission errors.

The -executable test (as well as the analogous -readable and -writable tests) are non-standard and require GNU find.

I can't (yet) say anything about the differences in result as you have said nothing about these. Since the output varies so drastically in size, it ought to be trivial to find and examine cases where one command found something that the other command did not find.

Kusalananda
  • 320,670
  • 36
  • 633
  • 936