Standard way to duplicate a file's permissions

10

4

I am trying to find a standard POSIX way to duplicate one file's permissions to another file. On a GNU system this is easy:

[alexmchale@bullfrog ~]$ ls -l hardcopy.*
-rw-r--r-- 1 alexmchale users 2972 Jul  8 20:40 hardcopy.1
---------- 1 alexmchale users 2824 May 14 13:45 hardcopy.4
[alexmchale@bullfrog ~]$ chmod --reference=hardcopy.1 hardcopy.4
[alexmchale@bullfrog ~]$ ls -l hardcopy.*
-rw-r--r-- 1 alexmchale users 2972 Jul  8 20:40 hardcopy.1
-rw-r--r-- 1 alexmchale users 2824 May 14 13:45 hardcopy.4

Unfortunately, the --reference flag to chmod is a non-standard option. So that is out for my purposes. I would prefer it to be a one-liner, but that's not necessary. Ultimately, it does need to be in POSIX sh syntax.

Alex

Posted 2010-07-31T13:40:13.203

Reputation: 665

Answers

7

One temptation is to parse ls. Avoid that temptation.

The following seems to work, however it is full of teh Kluge. It relies on cp retaining the permissions of the target file. For this demo, the file "template" must not already exist.

  • Copy the file with the permissions you want to a new file
  • Copy the file that you want to change to the file created in the previous step
  • Remove the original file that you want to change
  • Rename the intermediate file to the name of the file to be changed

Demo:

$ echo "contents of has">has
$ echo "contents of wants">wants
$ chmod ug+x has     # just so it's different - represents the desired permissions
$ cp has template
$ cat has
contents of has
$ cat wants
contents of wants
$ cat template
contents of has
$ ls -l has wants template
-rwxr-xr-- 1 user user 16 2010-07-31 09:22 has
-rwxr-xr-- 1 user user 16 2010-07-31 09:23 template
-rw-r--r-- 1 user user 18 2010-07-31 09:22 wants
$ cp wants template
$ ls -l has wants template
-rwxr-xr-- 1 user user 16 2010-07-31 09:22 has
-rwxr-xr-- 1 user user 18 2010-07-31 09:24 template
-rw-r--r-- 1 user user 18 2010-07-31 09:22 wants
$ cat template
contents of wants
$ rm wants
$ mv template wants
$ ls -l has wants
-rwxr-xr-- 1 user user 16 2010-07-31 09:22 has
-rwxr-xr-- 1 user user 18 2010-07-31 09:24 wants
$ cat has
contents of has
$ cat wants
contents of wants

Paused until further notice.

Posted 2010-07-31T13:40:13.203

Reputation: 86 075

The first cp command, cp has template, should use cp -p to preserve the mode and ownership attributes. – mernst – 2014-12-23T05:40:07.720

@mernst: That's only necessary for the first cp if the owner/group of the file (e.g. "user") is different from the one doing the copying (e.g. root). – Paused until further notice. – 2014-12-23T14:03:54.160

@Dennis Willamson: OK, but that is a possibility and I don't see any downside to using cp -p there. – mernst – 2014-12-24T15:08:11.327

Now that's an interesting approach. I'm going to test this out and see how well it works against various servers. It seems to me like it'll do the trick. – Alex – 2010-08-01T00:00:17.607

@Alex: make sure to test it with file ownership, too, if that's a concern. – Paused until further notice. – 2010-08-01T01:28:28.583

11

You can use the stat command to get the file permission :

  • Mac OS X (BSD) syntax :

    chmod `stat -f %A fileWithPerm` fileToSetPerm

  • Linux syntax (not sure) :

    chmod `stat -c %a fileWithPerm` fileToSetPerm

The ` symbol is a backquote.

Studer

Posted 2010-07-31T13:40:13.203

Reputation: 3 448

1I don't think stat is required by POSIX. It's often not available. – Paused until further notice. – 2010-07-31T17:52:06.467

stat (command line) is not POSIX, and is not portable. Dennis++ – jim mcnamara – 2010-08-02T11:38:20.130

1

ACL utilities getfacl and setfacl can be used for this purpose, but I don't know if this POSIX compliant enough. Works at least in FreeBSD 8.0 and Linux, but on the other hand one might have to install the ACL utilities.

From the man-page:

getfacl file1 | setfacl -b -n -M - file2
Copy ACL entries from file1 to file2.

I think getfacl and setfacl can operate also standard file permissions in addition to ACL's.

Janne Pikkarainen

Posted 2010-07-31T13:40:13.203

Reputation: 6 717

ACLs and such are defined by POSIX is implementation-specific, so it's not required for compliance. – Paused until further notice. – 2010-07-31T17:56:04.490

0

cp -p will preserve file permissions.

user31894

Posted 2010-07-31T13:40:13.203

Reputation: 2 245

1That's why the technique in my answer (of not using -p) works for what the OP wants which is to duplicate permissions for a different file, not a duplicate of the file. – Paused until further notice. – 2010-08-01T01:45:08.167

0

One portable, straightforward way is not a standard utility - you would need to call stat() on the templatefile, then chmod() on the destination file(s). This means using a language like C or another widely used language like perl.

The file access permissions are specified in the struct stat st_mode member by the 0007777 bits. Dennis' solution is correct, if a bit heavy on I/O, so for really big files it may fail:

cp has template

Consider this not-ready-for-production example:

#include <sys/types.h>
#include <sys/stat.h>
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <errno.h>

mode_t 
getperm(const char *template_file)
{
    struct stat st;
    if(stat(template_file, &st)==-1)
    {
       perror("Cannot stat file");
       exit(1);
    }
    return st.st_mode;
}

int main(int argc, char **argv)
{    
    mode_t mode=getperm(argv[1]);
    int i=0;
    for(i=2; argv[i]!=NULL; i++)    
    {
       if(chmod(argv[i], mode)==-1)
          fprintf(stderr, "Permissions failed on %s:\n\t%s\n",
              argv[i], strerror(errno));
    }       
    return 0;
}

jim mcnamara

Posted 2010-07-31T13:40:13.203

Reputation: 769