2

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?

muru
  • 72,889

5 Answers5

4

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
Thomas Dickey
  • 76,765
2

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/'
Rahul
  • 13,589
2

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.

Thawn
  • 1,002
  • 7
  • 13
  • 2
    grep -e "-r[rwx-]{8}" is probably a bit nicer to read – Michael Jun 06 '16 at 11:57
  • 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
1

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'
  • 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
0

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