shell script to create empty files with all possible permissions

Issue

How to write a shell script that creates empty files with all possible permissions. File names should be, for example, rwxrw_r__.txt. I know how to do it manually. As an example:

#!/bin/bash

touch task5/rwxrwxrwx.txt | chmod 777 task5/rwxrwxrwx.txt
touch task5/rwxr-xr-x.txt | chmod 755 task5/rwxr-xr-x.txt
touch task5/rwx------.txt | chmod 700 task5/rwx------.txt
touch task5/rw-rw-rw-.txt | chmod 666 task5/rw-rw-rw-.txt
touch task5/rw-r--r--.txt | chmod 644 task5/rw-r--r--.txt
touch task5/rw-------.txt | chmod 600 task5/rw-------.txt

I do not know how to write a script that will create files according to the required template and give them permissions

Solution

It’s just a permutations problem.

p=( --- --x -w- -wx r-- r-x rw- rwx ) # the set of permissions 
for u in "${p[@]}"; do for g in "${p[@]}"; do for o in "${p[@]}"; do
  f="task5/$u$g$o.txt"; touch -- "$f" && chmod "u=$u,g=$g,o=$o" -- "$f" 
done; done; done

This took a little over a minute on my laptop.

Let’s break it down and look at what’s happening.

If you have any questions about what permissions sets mean or how chmod works, see here.

So for each of the user, group, or other, there are eight possible symbolic representations (representing the values of one octal digit, 0-7).

We set those into a simple array we can loop over.

p=( --- --x -w- -wx r-- r-x rw- rwx ) # the set of permissions 

You can access any element with it’s octal digit (technically the decimal equivalent, but that doesn’t matter unless you go over 7) so ${p[5]} is r-x. Indexing with @ returns the whole array, so the loops walk through them sequentially with ${p[@]}.

To get every possible permutation, we loop over them for each of user/group/other.

for u in "${p[@]}"; do # assign each permission set for the user
for g in "${p[@]}"; do # assign each permission set for the group
for o in "${p[@]}"; do # assign each permission set for the other

This is just simple iterations in nested loops to hit every permutation.

  f="task5/$u$g$o.txt" # assign the permissions string AS the filename

By putting the path and filename info into a variable, we can maintain any changes in one place, and it makes the rest of the line shorter and easier to read.

  touch -- "$f" && # create the file and test for success

touch will create an empty file. Because the filenames could sometimes begin with a dash (any time the permissions dissalow user read), we give touch a first argument of --, which is a *NIX standard idiom meaning "options are done now, anything left is arguments"; otherwise it would try to interpret a leading dash as an invalid option set and fail. This won’t be a problem while you are putting "task5/" at the beginning of the filename, but if you end up using the filename bare it would.

The && is a boolean test to see whether touch succeeded. If it did not, then we silently skip trying the chmod (touch should have emitted an error message for your debugging, but if that fails, you probably got a ton of them, and will need to fix whatever …)

  chmod "u=$u,g=$g,o=$o" -- "$f" # change the permissions

This uses chmod‘s symbolic mode. We have the permissions of each section from the nexted loops – just apply them. Again, we use the -- to tell chmod when we are done passing options so that leading dashes won’t be a problem later if you refactor just just cd into the directory and create the files locally, though even then you could always prefic ./ or $PWD/ on it.

done; done; done # these just close each of the loops

We could (and probably should) put each of these on separate lines, but the interpreter doesn’t care since we used semicolons. It lets us compact the code to put the loop nesting and closures on lines together, so long as you are comfortable with the ONE thing that’s changing being obvious enough.

Anything you still have questions about that I didn’t cover?

Answered By – Paul Hodges

This Answer collected from stackoverflow, is licensed under cc by-sa 2.5 , cc by-sa 3.0 and cc by-sa 4.0

Leave a Reply

(*) Required, Your email will not be published