How can I reset permission to default according to the mask, so they will have permissions set as the file was just created

Example of what I want to achieve: umask is set to 0022 so

touch file
mkdir directory

file's permissions now are rw-r--r--

directory's permissons now are rwxr-xr-x

chmod 777 file
chmod 777 directory

file's permissions now are rwxrwxrwx

directory's permissions now are rwxrwxrwx

is there a way to reset perms back to default so file will be rw-r--r-- and directory rwxr-xr-x using chmod?


Using subtraction is only correct for some umask values - it's better to use mode & ~umask, like in PSkocik's answer, or chmod =rw (or chmod =rwx for directories) which applies the umask as specified by the standard, as noted by ilkkachu in the comments.

In some cases, you can just subtract the umask from 0666 for files and 0777 for directories to get default permissions:

$ printf "%04d\n" "$((0777 - $(umask)))"
$ printf "%04d\n" "$((0666 - $(umask)))"

Accordingly, you can apply chmod:

chmod $((0666 - $(umask))) file
chmod $((0777 - $(umask))) directory

In bash, you have to use printf to force the output in octal:

$ printf "%04d\n" "$((0777 - $(umask)))"
$ printf "%04o\n" "$((0777 - $(umask)))"

Another way would be to create a new file and directory, and use them as reference:

touch file2
mkdir directory2 
chmod --reference=directory2 directory
chmod --reference=file2 file
  • 3
    also I found something like chmod =rwx file, not sure what exactly it does but looks like it resets permissions to default too but only for directories – lllook Dec 16 '15 at 23:08
  • 1
    Note that Bash, unlike ZSH, treats values beginning with 0 as octal values. For these examples to work in Bash, the numbers need to be prefixed with 10#. For example: chmod $((10#0666 - 10#$(umask))) file – John Karahalis Jan 5 at 20:46
  • The produces incorrect results for files if the umask has “1” anywhere (uncommon perhaps but still possible). umask isn’t subtracted. – Stephen Kitt May 25 at 10:59
  • @JohnKarahalis, as long as there's no carry, it doesn't matter if the numbers are taken as octal or decimal. E.g. 6 - 4 = 2 in either. 4 - 6 would differ, though. But like Stephen says, the umask shouldn't be subtracted but bitwise modified. So we need the numbers to be interpreted correctly. In Bash, Dash, and Ksh, printf "%o\n" "$(( 0666 & ~$(umask) ))" should work. Zsh needs printf "%o\n" "$(( 8#0666 & ~8#$(umask) ))", but then that doesn't work in Dash. – ilkkachu May 25 at 14:49
  • 2
    chmod =rwx file also works, it sets the permissions to 0777 modified by the umask. See the sentences with "if who is not specified" in pubs.opengroup.org/onlinepubs/9699919799.2018edition/utilities/… – ilkkachu May 25 at 14:52

The masks are applied via bitwise AND with the bitwise negated mask so if you want to create your own final permission mode, you can do:

$((mode & ~umask))

You'll need to print that back in octal so that you can pass it to chmod:

$ chmod `printf '%o' $((0777 & ~$(umask)))` directory
$ chmod `printf '%o' $((0777 & ~0111 & ~$(umask)))` file
#^additional implicit mask of 0111 for files

where 0777 is the permission mode you want to apply the mask to (you can obtain it with stat -c %a file or stat -c %a directory).

You can echo the above to see what the process substitution will evaluate to (for an umask of 0022, you will get 755 and 644).

You could make a generic function out of it:

#takes a umask as first param and applies it to each folowing param (files)
  local mask="$1" dmask mode a
  dmask="$((mask & ~0111))"; shift
  for a; do
    mode=0`stat -c "%a" "$a"`
    chmod `printf "%0.4o\n" $(($mode & ~mask))` "$a"

For your particular use, chmod reference files are another option.


If you want to do it recursively through the current directory -

chmod -R $((777 - `umask`)) .
chmod -R -x+X .

You can replace `umask` with $(umask).

  • Backquotes, not single quotes – nomad May 15 at 6:21

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.