【问题标题】:How can I get octal file permissions with Ruby?如何使用 Ruby 获得八进制文件权限?
【发布时间】:2017-09-11 03:51:24
【问题描述】:

我阅读了 another answer 以了解如何使用 perl 获取 octal file permissions

$ 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

到目前为止,我已经使用了 File::Stat 类和 #printf 方法。但是,我的所有输出都领先 100 分。

$ ruby -e 'Dir["**/**"].each { |f| printf "%04o\t#{f}\n", File.stat(f).mode }'
100711  cplink
100644  hello_world.rb
100755  lso
100711  rename_images
  • 如果我在 macOS 计算机上,前导 100 是什么意思?
  • 为什么我的"%04o" 不起作用?
  • 如何实现与链接的 perl 脚本相同的输出?

【问题讨论】:

  • 这只是 File::Stat#mode 方法的返回值,完全正确,如文档中的示例所示。
  • 但是为什么会有 100 个呢?
  • 因为这就是 File::Stat#mode 返回的内容,完全按照文档。正如文档所说,File::Stat#mode 的返回值取决于平台,显然,在您的平台上,这就是它返回的值。
  • ruby oneliner 在你的机器上返回了什么?

标签: ruby unix file-permissions


【解决方案1】:

如果您查看 libc 手册的第二部分(来自 shell 的man 2 stat),您应该会看到如下内容:

状态信息字st_mode具有以下位:

#define S_IFMT   0170000  /* type of file */
#define S_IFIFO  0010000  /* named pipe (fifo) */
#define S_IFCHR  0020000  /* character special */
#define S_IFDIR  0040000  /* directory */
#define S_IFBLK  0060000  /* block special */
#define S_IFREG  0100000  /* regular */
#define S_IFLNK  0120000  /* symbolic link */
#define S_IFSOCK 0140000  /* socket */
#define S_IFWHT  0160000  /* whiteout */
#define S_ISUID  0004000  /* set user id on execution */
#define S_ISGID  0002000  /* set group id on execution */
#define S_ISVTX  0001000  /* save swapped text even after use */
#define S_IRUSR  0000400  /* read permission, owner */
#define S_IWUSR  0000200  /* write permission, owner */
#define S_IXUSR  0000100  /* execute/search permission, owner */

精确的内容不会完全相同,但八进制值在任何 Unixy 系统上应该是相同的。

您感兴趣的部分是“这是一个常规文件”位:

#define S_IFREG  0100000  /* regular */

这就是您领先的100 的来源。

如果您回顾一下 Perl 版本,您会发现它们正在应用位掩码:

(stat)[2] & 07777
          ^^^^^^^

只获取权限位。如果你在 Ruby 中做同样的事情:

printf "%04o\t#{f}\n", (File.stat(f).mode & 07777)
# ----------------------------------------^^^^^^^

你会得到你期望的那种输出。


如果您没有 libc 手册页,那么您可以查看 OpenGroup's stat documentation,它会将您指向 struct stat documentation,它涵盖了该模式中的各个位:

┌─────────┬───────────┬───────────────────────────────────────────┐
│ Name    │  Numeric  │               Description                 │            
│         │   Value   │                                           │            
├─────────┼───────────┼───────────────────────────────────────────┤
│ S_IRWXU │ 0700      │ Read, write, execute/search by owner.     │ 
├─────────┼───────────┼───────────────────────────────────────────┤
│ S_IRUSR │ 0400      │ Read permission, owner.                   │            
├─────────┼───────────┼───────────────────────────────────────────┤
│ S_IWUSR │ 0200      │ Write permission, owner.                  │            
├─────────┼───────────┼───────────────────────────────────────────┤
│ S_IXUSR │ 0100      │ Execute/search permission, owner.         │
├─────────┼───────────┼───────────────────────────────────────────┤
│ S_IRWXG │ 070       │ Read, write, execute/search by group.     │ 
├─────────┼───────────┼───────────────────────────────────────────┤
│ S_IRGRP │ 040       │ Read permission, group.                   │            
├─────────┼───────────┼───────────────────────────────────────────┤
│ S_IWGRP │ 020       │ Write permission, group.                  │            
├─────────┼───────────┼───────────────────────────────────────────┤
│ S_IXGRP │ 010       │ Execute/search permission, group.         │
├─────────┼───────────┼───────────────────────────────────────────┤
│ S_IRWXO │ 07        │ Read, write, execute/search by others.    │ 
├─────────┼───────────┼───────────────────────────────────────────┤
│ S_IROTH │ 04        │ Read permission, others.                  │            
├─────────┼───────────┼───────────────────────────────────────────┤
│ S_IWOTH │ 02        │ Write permission, others.                 │            
├─────────┼───────────┼───────────────────────────────────────────┤
│ S_IXOTH │ 01        │ Execute/search permission, others.        │
├─────────┼───────────┼───────────────────────────────────────────┤
│ S_ISUID │ 04000     │ Set-user-ID on execution.                 │            
├─────────┼───────────┼───────────────────────────────────────────┤
│ S_ISGID │ 02000     │ Set-group-ID on execution.                │
├─────────┼───────────┼───────────────────────────────────────────┤
│ S_ISVTX │ 01000     │ On directories, restricted deletion flag. │
└─────────┴───────────┴───────────────────────────────────────────┘

【讨论】:

    【解决方案2】:

    如果我使用的是 macOS 机器,前 100 位是什么意思?

    File::Stat#mode 方法的返回值取决于平台,显然,这就是它在您的平台上返回的值。

    特别是,文档说对于 Unix 机器,使用来自 stat(2) 的定义,on macOS 如下:

    状态信息字st_mode具有以下位:

    #define S_IFMT 0170000           /* type of file */
    #define        S_IFIFO  0010000  /* named pipe (fifo) */
    #define        S_IFCHR  0020000  /* character special */
    #define        S_IFDIR  0040000  /* directory */
    #define        S_IFBLK  0060000  /* block special */
    #define        S_IFREG  0100000  /* regular */
    #define        S_IFLNK  0120000  /* symbolic link */
    #define        S_IFSOCK 0140000  /* socket */
    #define        S_IFWHT  0160000  /* whiteout */
    #define S_ISUID 0004000  /* set user id on execution */
    #define S_ISGID 0002000  /* set group id on execution */
    #define S_ISVTX 0001000  /* save swapped text even after use */
    #define S_IRUSR 0000400  /* read permission, owner */
    #define S_IWUSR 0000200  /* write permission, owner */
    #define S_IXUSR 0000100  /* execute/search permission, owner */
    

    这与Single Unix Specification 中的描述相符,因此对于所有 Unices 或多或少都是如此,而不仅仅是macOS。 (macOS 有额外的“whiteout”文件类型,它与 Time Machine、AFAIK 相关,但没关系,SUS 允许额外的文件类型和权限位。)

    所以,如果我理解正确,这意味着hello_world.rb

    • 常规文件,而不是 fifo、字符设备、目录、块设备、符号链接、套接字或 whiteout
    • 不适合
    • 不是 sgid
    • 不粘
    • 可读可写,但其所有者不可执行
    • 可读,但组不可写或可执行
    • 可读,但其他人不可写或可执行

    为什么我的"%04o" 不起作用?

    %04o 表示“格式为八进制,最小长度为 4,如果长度小于 4,则用零填充”。这正是它的作用。

    如何实现与链接的 perl 脚本相同的输出?

    如果你想得到相同的输出,你应该做同样的事情:Perl 脚本从模式中屏蔽掉文件类型,如果你在 Ruby 中做同样的事情,你应该得到相同的结果:

    Dir["**/**"].each { |f| printf "%04o\t#{f}\n", File.stat(f).mode & 07777 }
    

    【讨论】:

      【解决方案3】:

      应该很简单:

      path = "file_with_0755"
      File.stat(path).mode.to_s(8).split("")[-4..-1].join
      # => "0755"
      File.stat(path).mode.to_s(8).split("")[-4..-1].join.to_i(8) == 0755
      # => true
      

      【讨论】:

      • split("")join 不是必需的
      • 确实如此,而且to_i(8)也不需要,你可以直接和“0755”比较。我将splitjoin 留给任何人想要单独使用每个代码的情况(就像我一样)
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2021-12-16
      • 2013-05-02
      • 2018-06-09
      • 1970-01-01
      • 2018-08-31
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多