将 ls -l 输出格式转换为 chmod 格式

Tyi*_*ilo 23 ls permissions chmod

假设我有以下输出ls -l

drwxr-xr-x 2 root root 4096 Apr  7 17:21 foo
Run Code Online (Sandbox Code Playgroud)

如何自动将其转换为使用的格式chmod

例如:

$ echo drwxr-xr-x | chmod-format
755
Run Code Online (Sandbox Code Playgroud)

我使用的是 OS X 10.8.3。

Sté*_*las 29

一些系统有命令将文件的权限显示为数字,但不幸的是,没有任何可移植的。

zsh在模块中有一个stat(又名zstat)内置stat

zmodload zsh/stat
stat -H s some-file
Run Code Online (Sandbox Code Playgroud)

然后,mode$s[mode]但是是模式,即类型+烫发。

如果您想要以八进制表示的权限,您需要:

perms=$(([##8] s[mode] & 8#7777))
Run Code Online (Sandbox Code Playgroud)

BSD(包括Apple OS/X)也有一个stat命令。

stat -f %Lp some-file
Run Code Online (Sandbox Code Playgroud)

(没有,则以八进制返回L完整模式

GNU find(从 1990 年开始,可能更早)可以将权限打印为八进制:

find some-file -prune -printf '%m\n'
Run Code Online (Sandbox Code Playgroud)

后来(2001 年,很久之后zsh stat(1997 年)但在 BSD stat(2002年)之前)stat又引入了一个具有不同语法的 GNU命令:

stat -c %a some-file
Run Code Online (Sandbox Code Playgroud)

早在这些之前,IRIX 已经有一个带有另一种语法的stat命令(在 1994 年的IRIX 5.3中已经有了):

stat -qp some-file
Run Code Online (Sandbox Code Playgroud)

同样,当没有标准命令时,可移植性的最佳选择是使用perl

perl -e 'printf "%o\n", (stat shift)[2]&07777' some-file
Run Code Online (Sandbox Code Playgroud)


man*_*ork 16

您可以stat使用该-c选项要求 GNU以八进制格式输出权限。来自man 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
Run Code Online (Sandbox Code Playgroud)

所以在你的情况下:

bash-4.2$ ls -l foo
-rw-r--r-- 1 manatwork manatwork 0 Apr  7 19:43 foo

bash-4.2$ stat -c '%a' foo
644
Run Code Online (Sandbox Code Playgroud)

或者您甚至可以通过将stat的输出格式化为有效命令来自动化它:

bash-4.2$ stat -c "chmod %a '%n'" foo
chmod 644 'foo'

bash-4.2$ stat -c "chmod %a '%n'" foo > setpermission.sh

bash-4.2$ chmod a= foo

bash-4.2$ ls -l foo
---------- 1 manatwork manatwork 0 Apr  7 19:43 foo

bash-4.2$ sh setpermission.sh 

bash-4.2$ ls -l foo
-rw-r--r-- 1 manatwork manatwork 0 Apr  7 19:43 foo
Run Code Online (Sandbox Code Playgroud)

如果使用通配符,上述解决方案也适用于多个文件:

stat -c "chmod -- %a '%n'" -- *
Run Code Online (Sandbox Code Playgroud)

将在包含空格字符的文件名上正常工作,但在包含单引号的文件名上将失败。

  • 我的 `stat` 没有 `-c` 选项。我使用的是 OS X 10.8.3。 (2认同)

Sté*_*las 13

为了从符号转换为八进制表示法,我曾经想出

chmod_format() {
  sed 's/.\(.........\).*/\1/
    h;y/rwsxtSTlL-/IIIIIOOOOO/;x;s/..\(.\)..\(.\)..\(.\)/|\1\2\3/
    y/sStTlLx-/IIIIIIOO/;G
    s/\n\(.*\)/\1;OOO0OOI1OIO2OII3IOO4IOI5IIO6III7/;:k
    s/|\(...\)\(.*;.*\1\(.\)\)/\3|\2/;tk
    s/^0*\(..*\)|.*/\1/;q'
}
Run Code Online (Sandbox Code Playgroud)

扩展:

#! /bin/sed -f
s/.\(.........\).*/\1/; # extract permissions and discard the rest

h; # store a copy on the hold space

# Now for the 3 lowest octal digits (rwx), translates the flags to
# binary where O means 0 and I means 1.
# l, L are for mandatory locking (a regular file that has 02000 on
# and not 010 on some systems like Linux). Some ls implementations
# like GNU ls confusingly use S there like for directories even though 
# it has nothing to do with setgid in that case. Some ls implementations 
# use L, some others l (against POSIX which requires an uppercase
# flag for extra flags when the execution bit is not set).
y/rwsxtSTlL-/IIIIIOOOOO/

x; # swap hold and pattern space, to do a second processing on those flags.

# now only consider the "xXlLsStT" bits:
s/..\(.\)..\(.\)..\(.\)/|\1\2\3/

y/sStTlLx-/IIIIIIOO/; # make up the 4th octal digit as binary like before

G; # append the hold space so we now have all 4 octal digits as binary

# remove the extra newline and append a translation table
s/\n\(.*\)/\1;OOO0OOI1OIO2OII3IOO4IOI5IIO6III7/

:k
  # translate the OOO -> 0 ... III -> 7 in a loop
  s/|\(...\)\(.*;.*\1\(.\)\)/\3|\2/
tk

# trim leading 0s and our translation table.
s/^0*\(..*\)|.*/\1/;q
Run Code Online (Sandbox Code Playgroud)

ls -l一个文件的输出返回八进制数。

$ echo 'drwSr-sr-T' | chmod_format
7654
Run Code Online (Sandbox Code Playgroud)