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?
Answers:
Thank you for visiting the Q&A section on Magenaut. Please note that all the answers may not help you solve the issue immediately. So please treat them as advisements. If you found the post helpful (or not), leave a comment & I’ll get back to you as soon as possible.
Method 1
On GNU/Linux chown and chmod have a --reference option
chown --reference=otherfile thisfile chmod --reference=otherfile thisfile
Method 2
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
Method 3
Did a bash command based on the response of Matteo 🙂
Code:
chmod $( stat -f '%p' "$1" ) "${@:2}"
Usage:
cp-permissions <from> <to>...
Method 4
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}
Method 5
This works for me:
cp -p --attributes-only <from> <to>
Method 6
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.
Method 7
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.
All methods was sourced from stackoverflow.com or stackexchange.com, is licensed under cc by-sa 2.5, cc by-sa 3.0 and cc by-sa 4.0