23

i have a tree of files with correct permission. then i have a (filewise) identical tree (with different file contents tough) with wrong permissions.

how can i transfer the permissions layout from one tree to another?

7 Answers 7

8

It can be done with the following shell line:

D1=foo; D2=foo2; for entry in $(find $D1  -exec stat -f "%N:%Mp%Lp" {} \;); do $(echo $entry | sed 's#'$D1'#'$D2'#' | awk -F: '{printf ("chmod %s %s\n", $2, $1)}') ; done

simply set the right value for D1 and D2 variables, point them to the source and destination directories, run and the dirs will have permissions in sync.

3
  • 1
    This assumes that stat is present. I've found, regrettably, that the command stat is often not present.
    – Mei
    Aug 25, 2009 at 9:02
  • 1
    @David, I don't know of such a system lacking of stat. But it is quite trivial to use the following "octal ls" version and accommodate the given solution accordingly: alias ols="ls -la | awk '{k=0;for(i=0;i<=8;i++)k+=((substr(\$1,i+2,1)~/[rwx]/)*2^(8-i));if(k)printf(\" %0o \",k);print}'"
    – drAlberT
    Aug 25, 2009 at 12:01
  • Breaks when any path involved contains any sort of special character (whitespace, starts with dashes, etc).
    – n.st
    Aug 4, 2017 at 17:13
34

I just learned a new and simple way to accomplish this:

getfacl -R /path/to/source > /root/perms.acl

This will generate a list with all permissions and ownerships.

Then go to one level above the destination and restore the permissions with

setfacl --restore=/root/perms.acl

The reason you have to be one level above is that all paths in perms.acl are relative.

Should be done as root.

3
  • this is a very straightforward and simple way to backup and restore permissions. Note however that getfacl and setfacl are not necessarily present on all systems.
    – the-wabbit
    Oct 24, 2013 at 14:58
  • Is it correct to have .ac in the first command and .acl in the second?
    – sfarbota
    Aug 2, 2017 at 21:54
  • 1
    @sfarbota: No, it was a typo! Corrected now. Thanks for pointing it out.
    – marlar
    Aug 4, 2017 at 15:25
14

If you have the source and dest, you can synchronize your permissions with rsync -ar --perms source/ dest

It will not transfer the data, just permissions...

3
  • 1
    nope, it will copy files if timestamps differ
    – yawniek
    Aug 25, 2009 at 8:50
  • @yawniek The -r and --perms are redundant, but this still sync perms if they are the only thing that is different (which is what you said in the Question; if the trees are not actually identical you should not have said that they were).
    – Chris S
    Feb 7, 2012 at 13:46
  • ok i was unclear then, i meant that the tree-structure is the same.
    – yawniek
    Apr 1, 2012 at 23:21
12

One thing you could do is use the find command to build a script with the commands you need to copy the permissions. Here is a quick example, you could do a lot more with the various printf options, including get the owner, group id, and so on.

$ find /var/log -type d -printf "chmod %m %p \n" > reset_perms
$ cat reset_perms
chmod 755 /var/log
chmod 755 /var/log/apt
chmod 750 /var/log/apache2
chmod 755 /var/log/fsck
chmod 755 /var/log/gdm
chmod 755 /var/log/cups
chmod 2750 /var/log/exim4
...
2
  • 1
    I suspect the -printf argument to find is a GNU extension? HP-UX find doesn't have it.
    – Mei
    Aug 25, 2009 at 9:04
  • 1
    Even without the printf option to find, one can use the ls option (or, at worst, pipe to xargs ls -l) and save in a file. A minute or two of search and replace, and one will have a script with chmod for each file.
    – mpez0
    Feb 26, 2010 at 14:34
0

Two ways:

  1. If it works on your brand of UNIX: cp -ax /src /dest
  2. Or if not, this is the portable version: (cd /src && tar cpf - .) | (cd /dst && tar xpf -)

(in the latter case /dst must exist)

Edit: sorry, I misread. Not what you asked.

1
  • It's worth mentioning that -a (for archive) is a GNU addition to cp, I've never seen it on any other system. It's just short for -dpR (no de-reference, recursive, preserve permissions). The R and p options should be in any version of cp Aug 25, 2009 at 8:34
0

I think I'd write a perl script to do it. Something like:

#!/usr/bin/perl -nw

my $dir = $_;
my $mode = stat($dir)[2];
my $pathfix = "/some/path/to/fix/";
chmod $mode, $pathfix . $dir;

Then do something like this:

cd /some/old/orig/path/ ; find . -type d | perlscript

I wrote this off the top of my head, and it has not been tested; so check it before you let it run rampant. This only fixes permissions on directories that exist; it won't change permissions on files, nor will it create missing directories.

0

I came up with this:

find $SOURCE -mindepth 1 -printf 'chmod --reference=%p\t%p\n'|sed "s/\t$SOURCE/ $DEST/g"|sh

It is not fully bullet proof, but does what I need.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge that you have read and understand our privacy policy and code of conduct.

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