Respostas:
Isso pode ser feito com a seguinte linha de shell:
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
simplesmente defina o valor correto para as variáveis D1 e D2, aponte-os para os diretórios de origem e destino, execute e os dirs terão permissões em sincronia.
Acabei de aprender uma maneira nova e simples de fazer isso:
getfacl -R /path/to/source > /root/perms.acl
Isso irá gerar uma lista com todas as permissões e propriedades.
Em seguida, vá para um nível acima do destino e restaure as permissões com
setfacl --restore=/root/perms.acl
A razão pela qual você precisa estar um nível acima é que todos os caminhos no perms.acl são relativos.
Deve ser feito como root.
getfacl
e setfacl
não está necessariamente presente em todos os sistemas.
.ac
no primeiro comando e .acl
no segundo?
Se você possui a origem e o destino, pode sincronizar suas permissões com
rsync -ar --perms source/ dest
Não irá transferir os dados, apenas permissões ...
-r
e --perms
são redundantes, mas isso ainda sincroniza permanentemente se forem a única coisa diferente (que foi o que você disse na pergunta; se as árvores não forem realmente idênticas, você não deveria ter dito que eram).
Uma coisa que você pode fazer é usar o comando find para criar um script com os comandos necessários para copiar as permissões. Aqui está um exemplo rápido: você poderia fazer muito mais com as várias opções printf, incluindo obter o proprietário, o ID do grupo e assim por diante.
$ 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
...
Dois caminhos:
(no último caso / dst deve existir)
Edit: desculpe, eu interpretei errado. Não é o que você pediu.
Eu acho que escreveria um script perl para fazer isso. Algo como:
#!/usr/bin/perl -nw
my $dir = $_;
my $mode = stat($dir)[2];
my $pathfix = "/some/path/to/fix/";
chmod $mode, $pathfix . $dir;
Então faça algo parecido com isto:
cd /some/old/orig/path/ ; find . -type d | perlscript
Eu escrevi isso em cima da minha cabeça e não foi testado; então verifique-o antes de deixá-lo correr desenfreado. Isso apenas corrige permissões nos diretórios existentes; não altera as permissões nos arquivos, nem cria diretórios ausentes.
Eu vim com isso:
find $SOURCE -mindepth 1 -printf 'chmod --reference=%p\t%p\n'|sed "s/\t$SOURCE/ $DEST/g"|sh
Não é totalmente à prova de balas, mas faz o que eu preciso.