ls -l 출력 형식을 chmod 형식으로 변환


17

다음과 같은 출력이 있다고 가정 해보십시오 ls -l.

drwxr-xr-x 2 root root 4096 Apr  7 17:21 foo

이것을 어떻게 사용되는 형식으로 자동 변환 할 수 chmod있습니까?

예를 들면 다음과 같습니다.

$ echo drwxr-xr-x | chmod-format
755

OS X 10.8.3을 사용하고 있습니다.


2
로 훨씬 쉬워 stat졌습니다. 당신은 그것을 가지고 있습니까? (이것은 GNU 도구이므로 대부분 유닉스가 아닌 리눅스에서 사용 가능합니다.)
manatwork

@manatwork가 stat foo제공합니다 16777219 377266 drwxr-xr-x 119 Tyilo staff 0 4046 "Apr 7 17:49:03 2013" "Apr 7 18:08:31 2013" "Apr 7 18:08:31 2013" "Nov 25 17:13:52 2012" 4096 0 0 /Users/Tyilo. 나는 755그것을 볼 수 없습니다 .
Tyilo

답변:


24

일부 시스템에는 파일의 권한을 숫자로 표시하는 명령이 있지만 불행히도 이식성이 없습니다.

zsh있다 stat(일명 zstat에서) 내장 stat모듈 :

zmodload zsh/stat
stat -H s some-file

그런 다음 mode$s[mode]있지만 모드는 + perms입니다.

사용 권한을 8 진수로 표시하려면 다음이 필요합니다.

perms=$(([##8] s[mode] & 8#7777))

BSD ( Apple OS / X 포함 )에도 stat명령이 있습니다.

mode=$(stat -f %p some-file)
perm=$(printf %o "$((mode & 07777))"

GNU find (1990 년과 그 이전까지)는 8 진수로 권한을 인쇄 할 수 있습니다.

find some-file -prune -printf '%m\n'

이후 (2001 년, zsh stat1997 년 이후, BSD stat(2002) 이전) GNU stat명령은 다른 구문으로 다시 도입되었습니다.

stat -c %a some-file

그보다 오래 전에 IRIX는 이미 다른 구문으로 1994 년 IRIX 5.3stat명령을 가지고있었습니다 .

stat -qp some-file

다시 말하지만 표준 명령이 없을 때 이식성을위한 최선의 방법은 다음을 사용하는 것입니다 perl.

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

15

옵션 stat을 사용하여 GNU 에게 8 진 형식으로 권한을 출력 하도록 요청할 수 있습니다 -c. 보낸 사람 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

따라서 귀하의 경우 :

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

또는 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

위의 솔루션은 와일드 카드를 사용하는 경우 여러 파일에서도 작동합니다.

stat -c "chmod -- %a '%n'" -- *

공백 문자가 포함 된 파일 이름에는 올바르게 작동하지만 작은 따옴표가 포함 된 파일 이름에는 실패합니다.


2
내가 stat이없는 -c옵션을 선택합니다. OS X 10.8.3을 사용하고 있습니다.
Tyilo

정보 @Tyilo에 감사드립니다. 죄송합니다. OS X 도구를 도와 드릴 수 없습니다.
manatwork

Mac OS X에서 맨 페이지 ^ W ^ W ^ W stat (1)을 stat -f 'chmod %p "%N"'
읽으십시오.

11

기호를 8 진수 표기법으로 변환하기 위해 한 번 생각해 냈습니다 .

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'
}

넓히는:

#! /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

ls -l한 파일 의 출력에서 ​​8 진수를 반환 합니다.

$ echo 'drwSr-sr-T' | chmod_format
7654

dpkg권한을 사용하여 권한을 "설치된 상태"로 다시 설정했습니다. 어떤 명령이 권한 문자열을 생성했는지에 관계없이 리터럴 질문에 대답 해 주셔서 감사합니다.
HiTechHiTouch

3

sh 아래 Mac에서이 명령

stat -f "%Lp %N" your_files

숫자 권한 만 원하는 경우 % Lp 만 사용하십시오.

예를 들면 다음과 같습니다.

stat -f "%Lp %N" ~/Desktop
700 Desktop

700은 chmod에서 사용할 수있는 숫자 권한이고 Desktop은 파일 이름입니다.


2

OP의 시도에서 영감을 얻은 질문 Y에 대한 답변 ( 질문 X 무시) 은 다음과 같습니다 .

#!/bin/bash
LC_COLLATE=C
while read ls_out
do
        extra=0
        perms=0
        for i in {1..9}
        do
                # Shift $perms to the left one bit, so we can always just add the LSB.
                let $((perms*=2))
                this_char=${ls_out:i:1}
                # If it's different from its upper case equivalent,
                # it's a lower case letter, so the bit is set.
                # Unless it's "l" (lower case L), which is special.
                if [ "$this_char" != "${this_char^}" ]  &&  [ "$this_char" != "l" ]
                then
                        let $((perms++))
                fi
                # If it's not "r", "w", "x", or "-", it indicates that
                # one of the high-order (S/s=4000, S/s/L/l=2000, or T/t=1000) bits
                # is set.
                case "$this_char" in
                  ([^rwx-])
                        let $((extra += 2 ** (3-i/3) ))
                esac
        done
        printf "%o%.3o\n" "$extra" "$perms"
done

위의 내용은 몇 가지 bashism을 포함합니다. 다음 버전은 POSIX 호환 인 것 같습니다.

#!/bin/sh
LC_COLLATE=C
while read ls_out
do
        extra=0
        perms=0
        for i in $(seq 1 9)
        do
                # Shift $perms to the left one bit, so we can always just add the LSB.
                : $((perms*=2))
                this_char=$(expr "$ls_out" : ".\{$i\}\(.\)")
                # Lower case letters other than "l" indicate that permission bits are set.
                # If it's not "r", "w", "x", or "-", it indicates that
                case "$this_char" in
                  (l)
                        ;;
                  ([a-z])
                        : $((perms+=1))
                esac
                # If it's not "r", "w", "x", or "-", it indicates that
                # one of the high-order (S/s=4000, S/s/L/l=2000, or T/t=1000) bits
                # is set.
                case "$this_char" in
                  ([!rwx-])
                        : $((extra += 1 << (3-i/3) ))
                esac
        done
        printf "%o%.3o\n" "$extra" "$perms"
done

노트:

  • LC_COLLATE=C그래서, ASCII 순서를 사용하는 등 치료 문자 시퀀스 범위 패턴에 쉘을 지시 [a-e]하는 것과 같습니다 [abcde]. 일부 로케일 (예를 들어, ko 페이지)에서 [a-e]와 동일 [aAbBcCdDeE] (예 [abcdeABCDE]) 또는 아마도 [abcdeABCD]- 참조 bash는 case 문은 대소 문자를 구분 없습니다 ... 왜? )
  • 두 번째 버전 (POSIX 호환 버전)에서 :

    • 첫 번째 case진술은 다시 쓸 수 있습니다.

              case "$this_char" in
                ([a-km-z])
                      : $((perms+=1))
              esac
      

      그러나 나는 지금 가지고있는 방식이 l 다르게 취급되고있는 글자임을 쉽게 알 수 있다고 생각합니다 . 또는 다음과 같이 다시 작성할 수 있습니다.

              case "$this_char" in
                ([rwxst])
                      : $((perms+=1))
              esac
      

      이후 r, w, x, s, 및 t적 모드 문자열 (이외에 나타납니다 유일한 문자입니다 l).

    • 두 번째 case진술은 다시 쓸 수 있습니다.

              case "$this_char" in
                ([rwx])
                      ;;
                ([A-Za-z])
                      : $((extra += 1 << (3-i/3) ))
               esac
      

      모드 비트를 지정하는 데 문자 만 유효하다는 규칙을 시행합니다. 대조적으로, 전체 스크립트에서 간결한 버전은 게으 르며에 -rw@rw#rw%해당하는 것으로  받아들 rwSrwSrwT입니다. 또는 다음과 같이 다시 작성할 수 있습니다.

              case "$this_char" in
                ([SsTtLl])
                      : $((extra += 1 << (3-i/3) ))
              esac
      

      이후 S, s, T, t, L, 및 l(이외의 적 모드 문자열에 표시하는 유일한 문자는 r, w, 및 x).

용법:

$ echo drwxr-xr-x | chmod-format
0755
$ echo -rwsr-sr-x | chmod-format
6755
$ echo -rwSr-Sr-- | chmod-format
6644
$ echo -rw-r-lr-- | chmod-format
2644
$ echo ---------- | chmod-format
0000

그리고 네, echo시작하는 텍스트 에는 사용하지 않는 것이 좋습니다 -. 방금 질문에서 사용법 예제를 복사하고 싶었습니다. 분명히 이것은 0 번째 문자 (즉, 선행 d/ b/ c/ -/ l/ p/ s/ D)와 10 번째 ( +/ ./ @)를 무시한다는 점에 유의하십시오 . 관리자 는 세 번째, 여섯 번째 또는 아홉 번째 위치에서 유효한 문자로 / 또는 / 을 ls정의하지 않을 것이라고 가정합니다 (그렇다면 스틱 으로 구타 해야합니다 ).rRwW


또한, 나는 단지로, 다음 코드를 발견 CAS 에서, 기본 그룹 / / var에 아래의 모든 파일의 사용자 소유권을 복원하는 방법 :

        let perms=0

        [[ "${string}" = ?r???????? ]]  &&  perms=$(( perms +  400 ))
        [[ "${string}" = ??w??????? ]]  &&  perms=$(( perms +  200 ))
        [[ "${string}" = ???x?????? ]]  &&  perms=$(( perms +  100 ))
        [[ "${string}" = ???s?????? ]]  &&  perms=$(( perms + 4100 ))
        [[ "${string}" = ???S?????? ]]  &&  perms=$(( perms + 4000 ))
        [[ "${string}" = ????r????? ]]  &&  perms=$(( perms +   40 ))
        [[ "${string}" = ?????w???? ]]  &&  perms=$(( perms +   20 ))
        [[ "${string}" = ??????x??? ]]  &&  perms=$(( perms +   10 ))
        [[ "${string}" = ??????s??? ]]  &&  perms=$(( perms + 2010 ))
        [[ "${string}" = ??????S??? ]]  &&  perms=$(( perms + 2000 ))
        [[ "${string}" = ???????r?? ]]  &&  perms=$(( perms +    4 ))
        [[ "${string}" = ????????w? ]]  &&  perms=$(( perms +    2 ))
        [[ "${string}" = ?????????x ]]  &&  perms=$(( perms +    1 ))
        [[ "${string}" = ?????????t ]]  &&  perms=$(( perms + 1001 ))
        [[ "${string}" = ?????????T ]]  &&  perms=$(( perms + 1000 ))

나는이 코드를 철저히 테스트하지는 않았지만 인식하지 못 l하거나 L여섯 번째 위치에 있다는 사실을 제외하고는 효과가있는 것 같습니다 . 그러나이 답변은 단순성과 명확성 측면에서 우수하지만 실제로는 짧습니다 ( 루프 내부 의 코드 만 -rwxrwxrwx계산하고 주석을 계산하지 않고 단일 문자열 을 처리하는 코드 ). 더 짧아 질 수 있습니다 대체하여 함께 .if condition; then …condition && …


물론 의 출력을 구문 분석해서는 안됩니다ls .


@ StéphaneChazelas : 좋아, 나는 말하고 #!/bin/sh몇 개의 bashism을 사용했다. 죄송합니다. 그러나 당신은 몇 가지를 놓쳤습니다 : 그리고 POSIX 인 것처럼 보이지도 않습니다 (표준은 전혀 언급하지 않았으며 다람쥐 와에 있습니다 ). 반대로, 나는 사용 하지 않았다 ; 이것은 cas 의 답변 에만 표시되며 여기 에서 인용 했습니다 . 또한 대답은 'l'과 'L'을 처리하며 cas의 대답이 그렇지 않다는 사실을 이미 지적했습니다. $(( variable++ ))$(( number ** number ))**++-- [[…]]
Scott

l / L에 대해 죄송합니다 [[, 너무 빨리 읽었습니다. 예,-및 ++는 POSIX가 아닙니다. POSIX는 쉘이이를 구현할 수 있도록합니다. 즉 $((- -a)), 이중 부정을 원할 경우 작성 해야 $((--a))하며 감소 조작을 의미 하지는 않습니다 .
Stéphane Chazelas

참고 seqPOSIX의 명령이 아닙니다. expr을 피하기 위해 $ {var #?} 연산자를 사용할 수 있습니다. LC_COLLATE가 LC_ALL을 대체하지는 않습니다.
Stéphane Chazelas

@ StéphaneChazelas : 자, cas의 답변에 대해 다시 이야기하고 있습니까? 그는 십진 산술을 사용하여 8 진수처럼 보이는 문자열을 구성하는 "게으른"접근 방식을 취하고 있습니다. 그의 모든 단계 값 (4000, 2000, 1000, 400, 200, 100, 40, 20 및 10)은 10 진수입니다. 그러나 8의 또는 9의 수가 7없고 소수 자릿수 이상을 얻을 수있는 방법이 없기 때문에 그는 the 드를 당길 수 있습니다. …………………… (이 의견은 사라진 스테판 샤젤 라스의 의견에 대한 답변입니다.)
Scott

예, 나중에 깨달았습니다. 그래서 댓글을 삭제했습니다.
Stéphane Chazelas

1

당신의 목표가 한 파일에서 권한을 가져 와서 다른 파일에게도 제공하는 것이라면, GNU는 chmod이미 "참조"옵션을 가지고 있습니다.


OP는 자신이 Apple OS / X에 있다고 언급 했으므로 chmodGNU가 아닙니다 chmod.
Stéphane Chazelas

아 그래, 나는 그들이 그들의 플랫폼을 말하는 다른 답변에 대한 의견을보고 있습니다. 비록 GNU만이 언급 된 것은 아니지만, Mac OS X에서 GNU 유틸리티를 얻을 수 있습니다
Bratchley

0

다른 방법으로, 권한을 저장하거나 나중에 복원하거나 다른 파일로 setfacl/getfacl복원하려는 경우을 사용하는 것이 좋으며, (POSIX-draft) ACL도 보너스로 복원합니다.

getfacl some-file > saved-perms
setfacl -M saved-perms some-other-file

(Solaris에서는 -f대신 사용 -M)

그러나 일부 BSD에서는 사용할 수 있지만 ACL 만 조작하는 Apple OS / X에는 없습니다 chmod.


0

Mac OS X (10.6.8) stat -f format에서는 실제로 NetBSD / FreeBSD이므로 사용해야 stat합니다.

# using Bash

mods="$(stat -f "%p" ~)"    # octal notation
mods="${mods: -4}"
echo "$mods"

mods="$(stat -f "%Sp" ~)"  # symbolic notation
mods="${mods: -9}"
echo "$mods"

ls -l쉘 권한 만 사용하여 8 진수로 작성된 기호 권한 문자열을 변환하려면 showperm.bash를 참조하십시오 .

# from: showperm.bash
# usage: showperm modestring
#
# example: showperm '-rwsr-x--x'
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.