Take the 2-minute tour ×
Super User is a question and answer site for computer enthusiasts and power users. It's 100% free, no registration required.

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.

share|improve this question
add comment

5 Answers

up vote 4 down vote accepted

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
share|improve this answer
    
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 Aug 1 '10 at 0:00
    
@Alex: make sure to test it with file ownership, too, if that's a concern. –  Dennis Williamson Aug 1 '10 at 1:28
add comment

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.

share|improve this answer
1  
I don't think stat is required by POSIX. It's often not available. –  Dennis Williamson Jul 31 '10 at 17:52
    
stat (command line) is not POSIX, and is not portable. Dennis++ –  jim mcnamara Aug 2 '10 at 11:38
add comment

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.

share|improve this answer
    
ACLs and such are defined by POSIX is implementation-specific, so it's not required for compliance. –  Dennis Williamson Jul 31 '10 at 17:56
add comment

cp -p will preserve file permissions.

share|improve this answer
1  
That'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. –  Dennis Williamson Aug 1 '10 at 1:45
add comment

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;
}
share|improve this answer
add comment

Your Answer

 
discard

By posting your answer, you agree to the privacy policy and terms of service.

Not the answer you're looking for? Browse other questions tagged or ask your own question.