Преобразуйте ls-l выходной формат к chmod формату

Необходимо добавить вызовы к complete к Вашей оболочке запускают файл (~/.tcshrc). По-видимому, Ваше поле SuSE предопределило правила для make; ищите их в /etc/csh.cshrc или некоторый другой файл, обеспеченный вместе с tcsh (rpm -ql tcsh).

tcsh распределение идет с некоторыми завершениями в качестве примера (Debian вставляет их /usr/share/doc/tcsh/examples/complete.tcsh.gz); вот тот для make:

complete make \
    'n/-f/f/' \
    'c/*=/f/' \
    'n@*@`cat -s GNUmakefile Makefile makefile |& sed -n -e "/No such file/d" -e "/^[^     #].*:/s/:.*//p"`@'
17
08.04.2013, 12:25
8 ответов

Некоторые системы имеют команды для отображения полномочий файла как число, но к сожалению, ничто портативное.

zsh имеет a stat (иначе zstat) встроенный в stat модуль:

zmodload zsh/stat
stat -H s some-file

Затем mode находится в $s[mode] но режим, который является типом + перманент.

Если Вы хотите полномочия, выраженные в восьмеричном, Вам нужно:

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

BSDs (включая Apple OS/X) имеют a stat команда также.

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

GNU находит (от еще 1990, и вероятно прежде) может распечатать полномочия как восьмеричные:

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

Позже (2001, намного позже zsh stat (1997) но перед BSD stat (2002)) GNU stat команда была представлена со снова другим синтаксисом:

stat -c %a some-file

Задолго до тех IRIX уже имел a stat команда (уже там в IRIX 5.3 в 1994) с другим синтаксисом:

stat -qp some-file

Снова, когда нет никакой стандартной команды, лучший выбор для мобильности состоит в том, чтобы использовать perl:

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

Можно спросить GNU stat производить полномочия в восьмеричном формате при помощи -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'" -- *

Будет работать правильно с именами файлов, содержащими пробельные символы, но перестанет работать на именах файлов, содержащих одинарные кавычки.

15
27.01.2020, 19:46
  • 1
    Мой stat не имеет a -c опция. Я использую OS X 10.8.3. –  Tyilo 07.04.2013, 20:15
  • 2
    Спасибо за информацию, @Tyilo. И извините, я не могу помочь с инструментами OS X. –  manatwork 08.04.2013, 09:25
  • 3
    Попытайтесь читать, manpage^W^W^W статистика (1) на Mac OS X имеют флаг-f для определения выходного формата, например. stat -f 'chmod %p "%N"' –  gelraen 08.04.2013, 16:56

Для преобразования от символьного до восьмеричной нотации я однажды придумал:

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 на одном файле.

$ echo 'drwSr-sr-T' | chmod_format
7654
12
27.01.2020, 19:46
  • 1
    я использовал это на выводе dpkg задерживать полномочия к, "как установлено". Спасибо за ответ на литеральный вопрос без учета, для которого команда произвела строку разрешения. –  HiTechHiTouch 08.02.2017, 15:44

Если Ваша цель состоит в том, чтобы взять полномочия из одного файла и дать их другому также, GNU chmod уже имеет "ссылочную" опцию для этого.

1
27.01.2020, 19:46

Альтернатива, если Вы хотите сохранить полномочия далеко, восстановить их позже, или на другом файле, должна использовать setfacl/getfacl, и это также восстановит (черновой POSIX) ACLs в качестве награды.

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

(на Солярисе использовать -f вместо -M).

Однако, хотя они доступны на некотором BSDs, они не находятся на Apple OS/X, где с ACLs управляют chmod только.

0
27.01.2020, 19:46

На 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 в восьмеричный (использование только окружают builtins) см.: showperm.bash.

# from: showperm.bash
# usage: showperm modestring
#
# example: showperm '-rwsr-x--x'
0
27.01.2020, 19:46

Эта команда на Mac под sh

stat -f "%Lp %N" your_files

, если вам нужно только цифровое разрешение, используйте только %Lp.

например:

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

700 - это разрешение на использование цифр, которое может быть использовано в chmod, а Desktop - это имя файла.

3
27.01.2020, 19:46

Команда replace не создает резервную копию sda1, она заменяет sda1 на sdb1 в файловой системе, но, поскольку это файловая система с одним устройством и btrfs, она не утруждает себя удалением данных из sda1, когда она заменяет ее, они становятся индентичными копиями файловой системы. Однако вы НЕ хотите делать это, так как оба будут иметь один и тот же UUID, и в настоящее время монтировать две файловые системы btrfs с тем же UUID небезопасно, так как это может вызвать МАССОВОЕ ПОВРЕЖДЕНИЕ ДАННЫХ (см. страницу btrfswiki в Gotchas) . Если вы хотите использовать функцию инкрементного резервного копирования btrfs, вы должны отформатировать диск резервного копирования/dev/sdb1 в новую файловую систему btrfs. Затем необходимо создать снимок подтома (ов) watever, которые требуется резервировать в файловой системе, только для чтения с помощью

btrfs su sn -r @subvolume-name @subvolume-name-RO

в каждом подтоме. Затем необходимо подключить пустую файловую систему btrfs и запустить

btrfs send /path/to/@subvolume-name-RO | btrfs rec /path/to/backup-directory/

. Это будет первая отправка, и btrfs должны будут передать все данные на этот раз. В следующий раз, когда вы хотите послать резервную копию в этот двигатель, вы можете использовать возрастающий, посылает, чтобы только послать то, что изменили данные начиная с предыдущей резервной копии вы послали. Это будет также использовать Копию На, Пишут, таким образом, вы оставите много свободного места также. Просто убедитесь, что в обеих файловых системах хранится последний снимок. После этого можно переименовать отправленный снимок в любой.

Теперь, если вы хотите отправить еще один снимок, просто переименуйте исходный и сделайте новый снимок с чем-то вроде

mv @subvolume-name-RO @subvolume-name-RO-old
btrfs su sn -r @subvolume-name @subvolume-name-RO

Тогда вы можете отправить последний снимок, используя

btrfs send -p @subvolume-name-RO-old @subvolume-name-RO | btrfs rec /path/to/backup-directory/

, и если предыдущий снимок все еще существует на вашем резервном диске, он отправит новый снимок, только если вам придется скопировать все изменения, внесенные с момента предыдущего.

-121--89217-

Используйте эти две команды от отдельных терминалов:

  1. , пока true; do dmesg -c > > test.txt; sleep 1; done
  2. tail -f test.txt

Это приведет к аналогичному результату.

-121--2093-

Вот ответ на вопрос 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

Приведённое выше содержит несколько башизмов. Следующая версия является 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] . В некоторых языковых системах (например, en_US), [a-e] эквивалентно [aAbBCdDeE] (т.е. [abcdeABCDE] ) или, возможно, [abcdeABCD] - См. Почему инструкция bash case не чувствительна к регистру...? )
  • Во второй версии (POSIX-совместимая):

    • Первая инструкция case может быть переписана:

        case «$ this _ char» в
      ([a-km-z])
      : $ ((допуски + = 1))
      esac
      

      но я думаю, что путь у меня сейчас это позволяет легче увидеть, что l письмо, которое обрабатывается по-другому. В качестве альтернативы его можно переписать:

        случай «$ this _ char» в
      ([rwxst])
      : $ ((допуски + = 1))
      esac
      

      с р , w , x , s и t являются единственными буквами это должно появиться в режиме последовательности (отличном от l ).

    • Вторая инструкция case может быть переписана:

        case «$ this _ char» в
      ([rwx])
      ;;
      ([A-Za-z])
      : $ ((дополнительно + = 1 < < (3-i/3)))
      esac
      

      , чтобы применить правило, согласно которому только буквы действительны для указания битов режима. (Напротив, более лаконичная версия в полном сценарии ленива, и примет -rw @ rw # rw% в качестве эквивалента rwSrwSrwT .) В качестве альтернативы его можно переписать:

        случай «$ this _ char» в
      ([SsTtLl])
      : $ ((дополнительно + = 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

И да, я знаю, что лучше не использовать эхо с текстом, который может начаться с - ; Я просто хотел скопировать пример использования из вопроса. Обратите внимание, очевидно, что это игнорирует 0-й символ (т.е. ведущие d / b / c / - / l / p / s / D ) и 10-й ( + /. /@). Предполагается, что сопровождающие ls никогда не будут определять r / R или w / W в качестве действительных символов в третьей, шестой или девятой позиции (и, если они это делают, их следует бить палками ).


Кроме того, я только что нашел следующий код, 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 , не считая комментариев), и его можно сделать еще короче заменой , если условие ; тогда... с условием & &... .


Конечно, не следует анализировать выходные данные ls .

2
27.01.2020, 19:46

Теги

Похожие вопросы