There's no convenient way. That's why GNU find added -readable
and friends.
You can build an expression that approximates the permission test by enumerating the groups that the user is in. Untested.
can_access="( -user $(id -u) -perm -0${oct}00 -o ("
for g in $(id -G); do
can_access="$can_access -group $g -o"
done
can_access="${can_access% -o} ) -perm -00${oct}0 -o -perm -000${oct} )"
find … $can_access -print
This doesn't give the correct result in some cases, for example if there are access control lists, or in edge cases such as -rw----r--
to deny access to a group. You can check for the edge cases with the same technique as above, but the expression gets even more complex. For access control lists, you need to invoke a tool that supports them.
Languages such as Perl and Python provide easy access both to the access(2)
function and to the functionality of find
. In Perl, with File::Find
and -r
/-w
/-x
(which use the effective uid and gid of the Perl process — use -R
/-W
/-X
to check with the real uid/gid like access(2)
, and use the filetest 'access'
pragma if your Perl isn't too ancient to have it to support things like ACL):
use File::Find;
use filetest 'access';
find(sub { if (-r $_) { print "$_ is readable\n"; } }, '.');
In Python, with os.walk
and os.access
(which uses the real uid and gid of the Python process, like access(2)
):
import os
for dirpath, dirnames, filenames in os.walk('.', ):
for filename in filenames:
filename = os.path.join(dirpath, filenames)
if os.access(filename, os.R_OK):
print(filename + ' is readable\n')
The only fully reliable way is to try to open the file. This requires an external utility, so it'll be slower. To test for readability of a regular file:
find … -exec sh -c 'exec 2>/dev/null; : <"$0"' {} \; …
To test for writability, use : >>"$0"
(this opens the file for appending, so it'll fail if the file isn't writable, but it doesn't actually modify anything, and in particular won't update the modification time). To test a directory for readability, use ls -- "$0" >/dev/null
. To test a directory for executability, use cd -- "$0"
.
There's no passive test for executability of a regular file, for writability of a directory, or for access to most non-regular files.