I'm trying to create a shell script where the command lists all the readable and executable permitted files for me or the current user, whomever it may be and wherever the location of the user. So even if I change permissions in the future, the changes will still be reflected.

This is what I have so far:

user=`id -un`
group=`id -gn`

for file in `ls -al /home/cg/root`; do
    perm=$(echo $file | awk '{print $1}')
    fileowner=$(echo $file | awk '{print $3}')
    filegroup=$(echo $file | awk '{print $4}')
    if ["$user"=="$fileowner" && "$ownerreadbit"=="r" && "$ownerexecbit"=="x"]; then
        echo $file
    elif ["$group"=="$filegroup" && "$groupreadbit"=="r" &&" $groupexecbit"=="x"]; then
        echo $file
    elif ["$worldreadbit"=="r" && "$worldexecbit"=="x"]; then
        echo $file

Why don't use the GNU find command?

find /home/cg/root -readable -executable

or only list the files:

find /home/cg/root -readable -executable -type f
  • And -writable for writable files ;-). – Stephen Kitt Mar 2 '18 at 13:44

User IporSricer's answer find /home/cg/root -readable -executable is the way to go. Note also that the find command has an added advantage of being able to customize the format of its output, including options to include many possible details about each file. Refer to option -printf in the man page. The main purpose of this answer is to try to provide useful feedback for your question for your future scripts.

  1. Don't use the output of ls for scripting! This is a common beginner mistake. ref Why *not* parse `ls`?

  2. Instead of using ls, just use the shell's native file globbing, eg. /home/cg/root/*. That's (one of the reasons) why the feature exists.

  3. Your script doesn't descend into sub-directories, but user IporSricer's answer does.

  4. You mis-use the substring expansion feature of the shell, so none of your tests whould work. The second parameter is a substring length, not am end position, so ${perm:1:2} returns a two-character substring; you want ${perm:1:1} for a single character substring.

  5. A quicker test would be to define separate varaiables of the form owner=${perm:1:2} and then test them against "rx".

  6. I'm surprised that you seem to say that && works inside a [ test command; I thought it should only work inside a [[.

  7. Since all three of your if, elif, elif are doing the same thing, an echo, you could combine them into a single if by using the || logical 'or' operator (outside the [ tests).

Hope that's useful.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.