GNU find -perm: Match Exact, All, or Any Permission Bits
A file with mode 0664 has group write set. GNU find -perm -022 skips it because that test needs both group write and other write. To list regular files under the current directory with either bit set, use /022.
find . -type f -perm /022 -print

Read the prefix before the digits
The last three octal digits are for owner, group, and other, in that order. In each digit, 4 is read, 2 is write, and 1 is execute. Add them to read a digit like 6, which means read and write. The mask 022 picks out group write and other write. The leading dash in -022 and the slash in /022 tell find how to check those same two bits.
| Test | When it matches |
|---|---|
-perm 0644 |
The mode is exactly 0644. |
-perm -0644 |
All bits selected by 0644 are set. Extra bits are allowed. |
-perm /022 |
Either write bit selected by 022 is set. Both also pass. |
-perm -022 |
Both write bits selected by 022 are set. |
-perm checks the mode bits on each entry. For a write-access check as the user running GNU find, there's a separate test called -writable. That test accounts for access control lists as well. GNU find manual on permission and access tests.
Predict which files pass
The lab puts six empty regular files in a directory called samples, which has mode 0777. Write down your matches before running the commands. In the first two questions, -type f limits the results to regular files.
| Name | Mode |
|---|---|
owner |
0644 |
group |
0664 |
other |
0646 |
both |
0666 |
executable |
0755 |
quiet |
0444 |
- Which files match
-perm 0644? Which match-perm -0644? Look closely at the bits inexecutableandquiet. - Which files match
-perm /022? Which match-perm -022? Decide whereownerbelongs even though it has a write bit. - Build the same regular-file search as the opening command using
-perm -020,-o, and-perm -002. Where do the parentheses go so-type fapplies to both branches? Then predict what happens tosamplesitself if you remove-type ffrom the/022search.
Run the lab on Linux
Check that find --version identifies GNU findutils, then paste the whole block into your shell as a regular user. The commands run in a separate shell, inside a private temporary directory that it removes on exit. The 0777 directory is inside that private directory.
sh <<'SH'
set -eu
umask 077
lab=$(mktemp -d /tmp/find-perm.XXXXXXXX)
trap 'cd / && rm -rf -- "$lab"' EXIT
cd "$lab"
mkdir samples
# Clear any special bits inherited by the new directory.
chmod 00777 samples
for name in owner group other both executable quiet; do
: > "samples/$name"
done
chmod 0644 samples/owner
chmod 0664 samples/group
chmod 0646 samples/other
chmod 0666 samples/both
chmod 0755 samples/executable
chmod 0444 samples/quiet
for mode in 0644 -0644 /022 -022; do
printf '\n%s\n' "$mode"
find samples -type f -perm "$mode" -printf '%f %m\n' > matches
LC_ALL=C sort matches
done
printf '\n%s\n' 'Grouped OR'
find samples -type f \( -perm -020 -o -perm -002 \) \
-printf '%f %m\n' > matches
LC_ALL=C sort matches
printf '\n%s\n' 'Without -type f'
find samples -perm /022 -printf '%p %m\n' > matches
LC_ALL=C sort matches
SH
GNU find's -printf can show the file name (%f), the path (%p), and the octal mode (%m). The displayed mode 644 is the same as 0644. Sorting gives the output a consistent order.
0644
owner 644
-0644
both 666
executable 755
group 664
other 646
owner 644
/022
both 666
group 664
other 646
-022
both 666
Grouped OR
both 666
group 664
other 646
Without -type f
samples 777
samples/both 666
samples/group 664
samples/other 646
Work through the matches
- Start with
executable. In0755, the owner digit7has read, write, and execute. Each5has read and execute. That covers everything in0644, so the file matches-0644. Its extra execute bits rule it out of the exact search.quietfails both searches because0444lacks owner write. Onlyownerhas exactly0644. - Check which class has the write bit.
grouphas group write,otherhas other write, andbothhas both. All three pass/022. Requiring both bits with-022leaves onlyboth. The write bit onowneris in the owner position, where022selects zero bits. - Apply
-type fto the whole OR. The grouped expression means regular file AND (group write OR other write). The backslashes pass the parentheses through the shell tofind. If you remove the group, the implicit AND binds more tightly than-o, so a directory with other write set can pass the right branch. In the last run,samplesappears becausefindalso checks the starting path, and mode0777satisfies/022. Find operator precedence with worked examples.
For a path list using POSIX syntax, use the grouped test and put -print after the closing parenthesis. The slash form is a GNU extension. POSIX find specification.
find . -type f \( -perm -020 -o -perm -002 \) -print
To work out whether a particular user can write a file, check which permission class applies and whether that user can traverse the parent directories. Linux file permissions practice.
Recall it without the table
| Front | Back |
|---|---|
Does a file with mode 0755 match -perm -0644? |
Yes. Every bit in 0644 is set. Extra execute bits are allowed. |
Which matches 0664, -perm /022 or -perm -022? |
/022 only. Group write is set and other write is clear. |
| Write the grouped OR for regular files with group or other write set. | -type f \( -perm -020 -o -perm -002 \) |
AI assisted with drafting, editing, and running the lab. The illustration is AI-generated. The lab ran with GNU findutils 4.10.0 and /bin/sh on aarch64 Linux in an Alpine 3.24.4 container.