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?

yawniek
  • 375
  • 1
  • 3
  • 10

7 Answers7

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.

marlar
  • 461
  • 6
  • 6
  • 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 '13 at 14:58
  • Is it correct to have `.ac` in the first command and `.acl` in the second? – sfarbota Aug 02 '17 at 21:54
  • 1
    @sfarbota: No, it was a typo! Corrected now. Thanks for pointing it out. – marlar Aug 04 '17 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...

Dom
  • 6,628
  • 1
  • 19
  • 24
  • 1
    nope, it will copy files if timestamps differ – yawniek Aug 25 '09 at 08: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 07 '12 at 13:46
  • ok i was unclear then, i meant that the tree-structure is the same. – yawniek Apr 01 '12 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
...
Zoredache
  • 128,755
  • 40
  • 271
  • 413
  • 1
    I suspect the -printf argument to find is a GNU extension? HP-UX find doesn't have it. – Mei Aug 25 '09 at 09: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 '10 at 14:34
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.

drAlberT
  • 10,871
  • 7
  • 38
  • 52
  • 1
    This assumes that stat is present. I've found, regrettably, that the command stat is often not present. – Mei Aug 25 '09 at 09: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 '09 at 12:01
  • Breaks when *any* path involved contains *any* sort of special character (whitespace, starts with dashes, etc). – n.st Aug 04 '17 at 17:13
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.

Thomas
  • 1,446
  • 11
  • 16
  • 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 – theotherreceive Aug 25 '09 at 08: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.

Mei
  • 4,560
  • 8
  • 44
  • 53
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.

Ikem Krueger
  • 101
  • 2