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?
On GNU/Linux chown
and chmod
have a --reference
option
chown --reference=otherfile thisfile
chmod --reference=otherfile thisfile
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}
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>...
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.
This works for me:
cp -p --attributes-only <from> <to>
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.
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.