Saturday, January 29, 2011

Copy permissions to identical tree on linux / unix

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?

  • 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...

    yawniek : nope, it will copy files if timestamps differ
    From Dom
  • 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
    ...
    
    David : I suspect the -printf argument to find is a GNU extension? HP-UX find doesn't have it.
    mpez0 : 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.
    From Zoredache
  • 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.

    Thomas : Find, sed and awk in one line. I love that (I do it too).
    yawniek : bit long but perfect! note: foo should be $D1
    David : This assumes that stat is present. I've found, regrettably, that the command stat is often not present.
    AlberT : @nemtester sure, corrected thanks :)
    AlberT : @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}'"
    From AlberT
  • 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.

    theotherreceive : 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
    From Thomas
  • 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.

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

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

    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.

    From marlar

0 comments:

Post a Comment