Respuestas:
Se puede hacer con la siguiente línea 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
simplemente configure el valor correcto para las variables D1 y D2, apúntelas a los directorios de origen y destino, ejecute y los directorios tendrán permisos sincronizados.
Acabo de aprender una forma nueva y sencilla de lograr esto:
getfacl -R /path/to/source > /root/perms.acl
Esto generará una lista con todos los permisos y propiedades.
Luego vaya a un nivel por encima del destino y restaure los permisos con
setfacl --restore=/root/perms.acl
La razón por la que tiene que estar un nivel por encima es que todas las rutas en perms.acl son relativas.
Debe hacerse como root.
getfacl
y setfacl
no están necesariamente presentes en todos los sistemas.
.ac
en el primer comando y .acl
en el segundo?
Si tiene el origen y el destino, puede sincronizar sus permisos con
rsync -ar --perms source/ dest
No transferirá los datos, solo permisos ...
-r
y --perms
son redundantes, pero esto todavía sincroniza permanentes si son lo único que es diferente (que es lo que dijo en la Pregunta; si los árboles no son realmente idénticos, no debería haber dicho que lo eran).
Una cosa que podría hacer es usar el comando find para crear un script con los comandos que necesita para copiar los permisos. Aquí hay un ejemplo rápido, podría hacer mucho más con las diversas opciones de printf, que incluyen obtener el propietario, la identificación del grupo, etc.
$ 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
...
Dos caminos:
(en este último caso / dst debe existir)
Editar: lo siento, leí mal. No es lo que preguntaste.
Creo que escribiría un script en perl para hacerlo. Algo como:
#!/usr/bin/perl -nw
my $dir = $_;
my $mode = stat($dir)[2];
my $pathfix = "/some/path/to/fix/";
chmod $mode, $pathfix . $dir;
Entonces haz algo como esto:
cd /some/old/orig/path/ ; find . -type d | perlscript
Escribí esto en la parte superior de mi cabeza, y no ha sido probado; así que verifíquelo antes de dejarlo correr desenfrenado. Esto solo corrige permisos en directorios que existen; no cambiará los permisos en los archivos, ni creará directorios faltantes.
Se me ocurrió esto:
find $SOURCE -mindepth 1 -printf 'chmod --reference=%p\t%p\n'|sed "s/\t$SOURCE/ $DEST/g"|sh
No es totalmente a prueba de balas, pero hace lo que necesito.