8

In my Linux box I have two directories:

  • work files with wrong permissions
  • older versions of the same files with the right permissions (permissions and users and groups)

I need to syncronize the permissions only without changing the file contents. I tried rsync but I can't find a suitable option. Can you give me some advice?

Thanks in advance.

EDIT

Thanks to your suggestions I have this script. It recursively changes the subtree permissions:

#!/bin/bash
cd good
find $1/* | while read DIR
do
 chown --reference="$DIR" "/bad/$DIR"
 chmod --reference="$DIR" "/bad/$DIR"
done

Not a masterpiece but it works for me.

Massimog
  • 83
  • 1
  • 7
  • 2
    use a for loop over the files and then execute for each file `chmod --reference=ReferenceFile` and `chown --reference=ReferenceFile` – mailq Nov 07 '11 at 16:52
  • Unless there's something else to it, Maliq's suggestion should work. Just holler if you need help with the script. – Jeffery Smith Nov 07 '11 at 17:31

2 Answers2

7

You can use the --reference=file switch to both chmod and chown to do this e.g.

#!/bin/bash
for FILE  in /path/to/good/directory/*
do
    chown --reference="$FILE" /path/to/bad/directory/"$(basename "$FILE")"
    chmod --reference="$FILE" /path/to/bad/directory/"$(basename "$FILE")"
done
user9517
  • 115,471
  • 20
  • 215
  • 297
0

You can try this. You need absolute paths for the 2 arguments required by this script. Run it like this copyperms.sh source_dir target_dir

Here is the script: cat copyperms.sh

#!/bin/bash

srcDir="$1"
targDir="$2"

if [ -z "$srcDir" ] || [ -z "$targDir" ]; then
    echo "Required argument missing."
elif [ ! -d "$srcDir" ] || [ ! -d "$targDir" ] ; then
    echo "Source and target not both directories."
    exit
else
    cd $srcDir

    echo "Source directory: $srcDir; Target directory: $targDir"
    echo "Matching permissions and ownerships .."
    find . -print0 | xargs -0I {} echo {} | xargs -I {} chmod --reference "{}" "$targDir/{}"
    find . -print0 | xargs -0I {} echo {} | xargs -I {} chown --reference "{}" "$targDir/{}"
    # find . | while read name
    # do
    #   chmod --reference "$name" "$targDir/$name"
    #   chown --reference "$name" "$targDir/$name"
    # done
    echo ".. done!"
fi

Can adapt for more uses by using the commented out while loop but it is slower ..

$ time mperms /adp/code /adp/safe/code

Using xargs:

real 0m0.107s user 0m0.008s sys 0m0.004s

Using while loop:

real 0m0.234s user 0m0.012s sys 0m0.028s sys 0m0.028s