This question seems an easy one for anyone who knows find command. But let's assume that find command doesn't work on my system. How can I view the files based on their permissions without using "find" command?
5 Answers
Without find
, you still have a shell (which can expand wildcards) and can loop over the contents of the directory checking first if each is a file, then if it is not writable, and then if it is not executable and then if it is readable.
Someone is likely to write a script to demonstrate, but it helps to start by reading the documentation, e.g., POSIX test.
By the way, the use of "only" in the question's title would exclude results where the file is either writable or executable. In POSIX find
, you can express it like this:
find . -type f \! \( -perm -u=w -o -perm -u=x -o -perm -g=w -o -perm -g=x -o -perm -o=w -o -perm -o=x \)
GNU find
provides extensions which allow more compact expressions:
find . -type f \! -perm /u=wx,g=wx,o=wx
The test
utility (more often used as [
and ]
) provides simpler tests than find
, e.g.,
for name in *; do [ -f "$name" -a -r "$name" -a ! -w "$name" -a ! -x "$name" ] && ls -l "$name"; done
However, its permissions are only for the user, not group or other. To exclude files based on those, you can use ls
, e.g.,
for name in *; do [ -f "$name" ] && case "$(ls -l "$name")" in -r--r--r--*) echo "$name";; esac; done
or (if you want to allow executable files)
for name in *; do [ -f "$name" ] && case "$(ls -l "$name")" in -r-?r-?r-*) echo "$name";; esac; done

- 76,765
you can use,
# for file in /your/path/*; do [ -r "$file" ] && [ -f "$file" ] && printf '%s\n' "$file"; done
-r
stands for, file exists and read permission is granted.
To find readable files regardless of owner, group or others, you can check the r
flag in the file permission column of ls.
ls -l | awk '$1 ~ /r/'

- 13,589
-
Not bad, but you can simplify it and increase robustness:
for f in /your/path/*; do [ -r "$f" ] && [ -f "$f ] && printf '%s\n' "$f"; done
. Also see Why is printf better than echo? and Why does my shell script choke on whitespace or other special characters? – Wildcard Jun 06 '16 at 22:18 -
@Wildcard why to use
[ -f $f ]
? because-r
itself checks for file existence and readable – Rahul Jun 07 '16 at 05:03 -
1
-f
checks that a file is a regular file.-r
checks for readability.[ -r somedirectory ]
will return true. Perhaps the Original Poster wanted to include readable directories in his results list, but when you're new to a language it's easier to remove the flags (options) you don't need than to add options you don't know, so I thought it better to assume he wanted regular files only. (Also, it's[ -f "$f" ]
, not[ -f $f ]
.) ;) – Wildcard Jun 07 '16 at 06:30 -
You could use ls -l
in conjunction with grep
:
ls -l | grep -e "-r[w-][x-][r-][w-][x-][r-][w-][x-]"
This would show you only files that you have read permission to. If you add [-d]
instead of the dash at the beginning of the pattern, you would get also directories.

- 1,002
- 7
- 13
-
2
-
2@Michael nicer to read yes, however I specifically chose the long version because it is more educational. Also, it is easier adapted to specific needs (by replacing a certain brace with the respective letter to be queried for). – Thawn Jun 06 '16 at 12:02
Along the lines of what Thawn said above,
aiming for the simplest solution as a priority
(and assuming you can use ls, since you can't use find
;
you could do ls -l | grep ^.r\-\-
to find exactly what you asked for,
"files that have read permission only..."
For example
touch testfile.txt
chmod 0400 testfile.txt
ls -l | grep ^.r\-\-
outputs
`-r-------- 1 youruser yourgroup 0 6 Jun 11:20 testfile.txt'

- 76
-
Obviously it might be a lot more "fun" to an experienced user to loop over the directory with scripts like many have already written here – olaf atchmi Jun 06 '16 at 09:45
With zsh
:
view ./*(.^f-444)
or:
view ./*(.r,.A,.R)
Would view the non-hidden regular files that have at least one of the read permission bits set. Equivalent of:
find . ! -name . -prune ! -name '.*' -type f \(
-perm -001 -o -perm -010 -o -perm -100 \)
or with GNU find
:
find . -maxdepth 1 ! -name '.*' -type f -perm /444
While:
view ./*(.e:'[ -r $REPLY ]':)
would view the non-hidden regular files that you have permission to read. Equivalent of:
find . ! -name . -prune ! -name '.*' -type f -exec test -r {} \; -print
Or with GNU find
:
find . -maxdepth 1 ! -name '.*' -type f -readable
And:
view ./*(.f-7333^f-444)
To view non-hidden regular files where only read permission bits (at least one) are set.
Equivalent of GNU find
's:
find . -maxdepth 1 ! -name '.*' -perms /444 ! -perms /7333

- 544,893
find
? – Rahul Jun 06 '16 at 09:24