Clone ownership and permissions from another file?

Is there a command or flag to clone the user/group ownership and permissions on a file from another file? To make the perms and ownership exactly those of another file?

Asked By: user394

||

On GNU/Linux chown and chmod have a --reference option

chown --reference=otherfile thisfile
chmod --reference=otherfile thisfile
Answered By: enzotib

If you are not using a system with GNU’s chmod/chown (which support the --reference option) you could try to parse the output of ls -l

Here a small script for chmod (if you have a see which supports extended regexes they could be written in a much more readable way …)

#!/bin/sh

reference=$1
shift
files=$*

# strip the permissions (whith extended regexes could be more readable)
OWNER=$(ls -l ${reference} | sed -e "s/.(...).*/1/"       | sed -e "s/[-]//g" )
GROUP=$(ls -l ${reference} | sed -e "s/....(...).*/1/"    | sed -e "s/[-]//g" )
OTHER=$(ls -l ${reference} | sed -e "s/.......(...).*/1/" | sed -e "s/[-]//g" )

chmod u=${OWNER},g=${GROUP},o=${OTHER} ${files}

UPDATE:

This is even easier using stat:

chmod $( stat -f '%p' ${reference} ) ${files}
Answered By: Matteo

On any unix with GNU utilities, such as (non-embedded) Linux or Cygwin, you can use chmod --reference and chown --reference.

If your system has ACLs, try the ACL commands getfacl and setfacl. These commands differ a little from system to system, but on many you can use getfacl other_file | setfacl -bnM - file_to_change to copy the permissions. This doesn’t copy the ownership; you can do that with careful parsing of ls -l other_file, assuming that you don’t have user or group names containing whitespace.

LC_ALL=C ls -l other_file | {
  read -r permissions links user group stuff;
  chown -- "$user:$group" file_to_change
}
getfacl other_file | setfacl -bnM - file_to_change

Did a bash command based on the response of Matteo 🙂

Code:

chmod $( stat -f '%p' "$1" ) "${@:2}"

Usage:

cp-permissions <from> <to>...

Answered By: mjlescano

I wanted to add an adjustment to Matteo‘s script. A for loop should be used to validate that the files exist before actually running the chmod command on them. This will let the script error out more gracefully.

I think this is the best option because it can be used for all *nix OSes, like Solaris, Linux, etc.

#!/bin/sh

reference=$1
shift
files=$*

for file in $reference $files; do
  [ -f $file ] || { echo "$file does not exist"; exit 1; }
done

# strip the permissions (whith extended regexes could be more readable)
OWNER=$(ls -l ${reference} | sed -e "s/.(...).*/1/" | sed -e "s/[-]//g" )
GROUP=$(ls -l ${reference} | sed -e "s/....(...).*/1/" | sed -e "s/[-]//g" )
OTHER=$(ls -l ${reference} | sed -e "s/.......(...).*/1/" | sed -e "s/[-]//g" )

chmod u=${OWNER},g=${GROUP},o=${OTHER} ${files}

I found that on one of my Solaris 10 machines, stat was not found. That might be an issue with my configuration though.

Answered By: David

This works for me:

cp -p --attributes-only <from> <to>

Answered By: user172554

On MacOS, cp --attributes-only or chmod --reference won’t work.

A solution for MacOS is to first install coreutils using

brew install coreutils

then use the coreutils‘s version of cp command, that is gcp:

gcp --attributes-only --archive  sourcefile destfile

This will copy the ownership and attributes while preserving destfile‘s content and filename.

Answered By: Sohail Si

I got inspired by @Matteo and @mjlescano. This one-liner works on MacOS without installing any additional dependencies.

permcp() { chmod $( stat -f '%A' "$1" ) "${@:2}" } && permcp sourcefile targetfile

We have just defined a function and called the function with source and target file parameters. You can use the "permcp" function for subsequent invocations if it’s required.

Answered By: caltuntas
Categories: Answers Tags: , , ,
Answers are sorted by their score. The answer accepted by the question owner as the best is marked with
at the top-right corner.