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

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

你可以试试

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/ 

(参考)

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

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

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

%A人类可读forms的访问权限

%八进制中的访问权限

%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

使用上述方法计算组和其他人的权限。 假设您希望授予所有者完全权限,读取和执行分组权限以及只读权限,则需要按如下方式计算权限:User = 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

正如Adam Courtemanche在AgileAdam.com上使用’ls’“755”式权限中所详述的那样 ,您可以创建一个别名 lso ,其行为类似于ls -l但稍微处理输出1以显示八进制权限。 这会添加一个显示三位数2个八进制权限的前导列。 如上所述,这适用于大多数文件和目录,但如果设置了sticky或setuid / setgid位,则无法正常工作。 3

 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 指出的那样 ,这有一个严重的缺点。 您不能像ls命令那样将参数传递给此lso别名,因为它们被视为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 人们可能会注意到这似乎忽略了关于不解析ls输出的一般规则 。 ls产生非常人性化的输出; 这引入了特性和限制,使其通常不适合作为其他命令的输入。 在这种情况下,我们解析ls因为我们希望保留ls的确切行为,除了我们添加的一个更改。

2 此别名的一个限制,也适用于下面显示的function版本,可能被认为是一个错误, 即使第四个八进制数字为零 ,它只显示三个八进制数字 正如jfmercer 正确指出的那样 ,这里显示的八进制数字不会反映粘性位(如果存在),也不会反映setuid或setgid位。

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

只需扩展\简化之前的’stat’相关答案:

你可以简单地运行:

 stat  

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

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

 # 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–)

为了便于携带,您可以使用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 

您可以在-printf操作中使用find

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

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

例如,要检查我的video目录:

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

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

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

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

find让您可以很好地控制它如何显示输出。 您可能会发现有两个特别有用的修改:

  • 默认情况下, find recurses子目录,类似于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 .... 

有关使用find命令的更多信息,请参阅man 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函数来编写。