如何从命令行获取八进制文件权限?


373

有一个chmod命令来设置文件权限,但是我可以从命令行以八进制模式(例如755)获得文件权限吗?


2
对于像我这样的人,这些人无意中登陆了此页面,但实际上正在Mac上搜索操作方法:stackoverflow.com/a/14855227/470749
Ryan

2
stat --format "%A" $FILE为您提供人类可读的drwxr-x---格式。这可能有用也可能没有用。
Trevor Boyd Smith,

Answers:


535

你可以试试

stat -c "%a %n" *

替换*为相关目录或您要检查的确切文件名。

stat手册页中

-c  --format=FORMAT
          use  the  specified  FORMAT instead of the default; output a newline after
          each use of FORMAT
%a     Access rights in octal
%n     File name

用法:

  • 带有文件:

    $ stat -c "%a %n" ./Documents/Udev.html 
    664 ./Documents/Udev.html
    
  • 带文件夹:

    $ stat -c "%a %n" ./Documents/
    755 ./Documents/
    

(参考)


57
在Mac OS上,使用stat -f '%A %a %N' *(来源:geeklog.adamwilson.info/article/58/…
s2t2

1
如果您对以下内容更满意lsfor f in $(ls -a); do stat -c "%a %n" $f; done;
usandfriends

2
@usandfriends循环输出ls是一个坏主意。如果您真的想使用循环,可以这样做for f in *; do stat "%a %n" "$f"; done
Tom Fenech

1
为什么在Mac OS上,所有内容都会略有变化(即使在UNIX iso utils中)?这有实际原因吗?
瓦西里斯

2
请@hackel,告诉我们您的真实感受。大声笑!
MikeSchinkel '17

44

Linux中的文件许可权可以使用Linux stat命令以八进制格式显示。

只需按键盘上的Ctrl+ Alt+ T打开终端。当它打开时,导航到要在八进制模式下查找文件权限的目录。

stat -c '%A %a %n' *

%A可读格式的访问权限

%a八进制访问权限

%n文件名

八进制数字和权限

您可以使用八进制数字表示模式/权限:

r: 4
w: 2
x: 1

例如,对于文件所有者,您可以如下使用八进制模式。八进制文件的读取,写入和执行(完全)权限为0 + r + w + x = 0 + 4 + 2 + 1 = 7

八进制文件的唯一读写权限是0 + r + w + x = 0 + 4 + 2 + 0 = 6

仅对八进制文件的读取和执行权限为0 + r + w + x = 0 + 4 + 0 + 1 = 5

使用以上方法来计算组和其他人的权限。假设您希望对所有者授予完全权限,对组具有读取和执行权限,而对其他用户则是只读权限,那么您需要按以下方式计算权限:用户= r + w + x = 0 + 4 + 2 + 1 = 7组= r + w + x = 0 + 4 + 2 + 0 = 6其他= r + w + x = 0 + 0 + 0 + 1 = 1

有效许可为761。

资料来源:http//kmaiti.blogspot.com/2011/09/umask-concept.html


2
开头的

36

AgileAdam.com亚当· 科特曼奇Adam Courtemanche)的带有“ ls”“ 755”式权限中所详细描述的,您可以创建一个别名,其作用类似于但稍微处理输出1以也以八进制显示权限。这将添加一个显示三位数2八进制权限的前导列。如所写,这适用于大多数文件和目录,但是如果设置了stickysetuid / setgid位,则无法正常工作。3 lsols -l

alias lso="ls -alG | awk '{k=0;for(i=0;i<=8;i++)k+=((substr(\$1,i+2,1)~/[rwx]/)*2^(8-i));if(k)printf(\" %0o \",k);print}'"

但是,正如techtonik 指出的那样,这有一个严重的缺点。你不能传递参数给这个lso别名,你会来ls命令,因为它们被作为附加参数来awk代替。因此,您不能lso在特定的文件或目录上运行,也不能将任何选项(例如-F--color)传递给lso


解决方法是将其定义lso 函数而不是别名。

lso() { ls -alG "$@" | awk '{k=0;for(i=0;i<=8;i++)k+=((substr($1,i+2,1)~/[rwx]/)*2^(8-i));if(k)printf(" %0o ",k);print}'; }

如果要在Shell中unalias lso以交互方式进行尝试,请运行以删除别名-您可以在定义函数之前或之后执行此操作。如果要将其放入源文件(例如)中~/.bashrc,只需删除该alias行并添加函数定义即可。

为什么这样做?与别名不同,bash shell函数可以采用位置参数,即命令行参数"$@"扩展到完整的参数列表,导致函数的参数lso传递到ls。(不同于一个别名定义,函数体不是引用;因此,有必要去除\之前的字符$"。)

由于您可以通过lso这种方式将选项传递给函数,因此您可能希望从定义中删除-a-G选项-如果需要,可以手动传递它们。(-l选项是必需的,如文件权限的详细信息,以显示在所有,所以没有好处移除它。)

lso() { ls -l "$@" | awk '{k=0;for(i=0;i<=8;i++)k+=((substr($1,i+2,1)~/[rwx]/)*2^(8-i));if(k)printf(" %0o ",k);print}'; }

由于techtonik指出的限制定义lso为一个别名,从而激励我与材料扩大这篇文章关于使其成为一个功能来代替。


1可能有人注意到这似乎违背了不解析来自的输出的一般规则lsls产生非常易于理解的输出;这引入了特质和限制,使其通常不适合作为其他命令的输入。在这种情况下,我们分析ls,因为我们希望保留的具体行为ls,除了我们的一个补充的变化。

2此别名的一个限制(也适用于其下方显示的功能版本,并且可能被视为错误)是,即使第四个八进制数字为零,它也只能显示三个八进制数字作为jfmercer已经正确地指出,这里显示的八进制数字不反映粘滞位如果存在的话,也不是setuid或setgid位。

3不仅仅是没有显示第四八进制数字更为严重的是,这种方法假设他们没有设置,并且如果他们是-如果你看到ts或者S在权限字符串-那么你应该忽略八进制数字。这是因为这些位是从权限字符串中以不考虑粘性setuid / setgid位的方式推断出来的。


-使用目录不起作用awk: read error (Is a directory)
阿纳托利techtonik

@techtonik感谢您指出这一点!我(最后)更新了此答案,以包括针对此问题的修复程序。
伊莱亚·卡根

1
您可以添加--color用于显示颜色的参数lso() { ls -alG "$@" --color | awk '{k=0;for(i=0;i<=8;i++)k+=((substr($1,i+2,1)~/[rwx]/)*2^(8-i));if(k)printf(" %0o ",k);print}'; }
tagplus5 '17

1
自发布此消息以来,您是否找到解决粘性setuid / setgid问题的解决方案?
Silvestris

21

只是扩展\简化了先前与“统计”相关的答案:

您可以简单地运行:

stat <path_to_file>

输出将包含八进制权限以及其他信息。



详细信息(统计版本和示例):

# stat --version
stat (GNU coreutils) 8.4


[user@localhost ~]# touch /tmp/TEST_PERMISSONS

[user@localhost ~]# chmod 644 /tmp/TEST_PERMISSONS

[user@localhost ~]# stat /tmp/TEST_PERMISSONS
  File: `/tmp/TEST_PERMISSONS'
  Size: 0           Blocks: 0          IO Block: 4096   regular empty file
Device: fd00h/64768d    Inode: 1010058     Links: 1
Access: (0644/-rw-r--r--)  Uid: (    0/    root)   Gid: (    0/    root)
Access: 2015-08-26 18:58:59.000000000 +0300
Modify: 2015-08-26 18:58:59.000000000 +0300
Change: 2015-08-26 18:59:16.000000000 +0300

请注意:(0644 / -rw-r--r--)


6

为了便于携带,您可以使用perl

$ perl -e 'printf "%04o %s\n", (stat)[2] & 07777, $_ for @ARGV' *.txt
0644 1.txt
0644 2.txt
0644 3.txt
0644 4.txt
0600 PerlOneLiner.txt
0664 perl.txt

如果您想在发生错误时注意,请尝试:

perl -e '
for (@ARGV) {
    print "$!: $_\n" and next unless -e;
    printf "%03o %s\n", (stat)[2] & 07777, $_;
}
' *.txt

2
除了具有可移植性之外,@ cuonglm的解决方案还显示四个八进制字符而不是三个八进制字符,从而显示了经常被遗忘的“粘性位”的状态。
jfmercer

2

您可以使用find-printf动作。

ls不显示八进制权限,但是您可以使用find基于此的解决方法:

find path -printf "%m:%f\n"

例如,要检查我的视频目录:

$ find Videos -printf "%m:%f\n"
755:Videos

%m格式说明符告诉-printf动作打印八进制的权限,而%f格式说明使打印的文件名。

您可以将多个文件名传递给find。您甚至可以使用glob(例如find * -printf "%m:%f\n")。

您不必使用类似-name或的测试-iname;只需将您感兴趣的文件或目录的名称作为起点传递给即可find。也就是说find,如上所示,在单词之后紧接提供其名称作为参数。

find使您可以很好地控制其显示输出的方式。特别有两个修改可能对您有用:

  • 默认情况下,find递归子目录,类似于ls -R。如果您不想find访问传递给起点的子目录,则可以添加-maxdepth 0(或-maxdepth与其他值一起使用,以指示您希望传递的深度)。

    $ find Documents -maxdepth 0 -printf "%m:%f\n"
    755:Documents
    
  • %f仅显示文件名,因此如果find必须递归才能访问文件,则可能不知道文件的位置。要显示路径,请以找到该文件的起点为起点%p

    $ find /boot -printf "%m:%p\n"
    755:/boot
    644:/boot/initrd.img-4.4.0-92-generic
    600:/boot/System.map-4.4.0-93-generic
    600:/boot/vmlinuz-4.4.0-92-generic
    600:/boot/vmlinuz-4.4.0-93-generic
    ....

请参阅man find有关使用find命令的更多信息。

另一种方法(lsawk

这可用于列出所有目录文件及其权限:

ls -l | awk '{k=0;for(i=0;i<=8;i++)k+=((substr($1,i+2,1)~/[rwx]/) \
             *2^(8-i));if(k)printf("%0o ",k);print}'

这基本上与Adam Courtemanche的lso别名中的命令相同,该命令引用了答案,只是作为单个命令运行。如果只使用一次,或者很少使用,那么您可能不希望将其作为别名或Shell函数编写。

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.