Встроенный способ перечисления разрешений на файлы в Linux?

Вопрос или проблема

Какие есть варианты, не используя внешние команды, для отображения разрешений файла?

test является встроенной командой, но, насколько я знаю, работает только для владельца файла. Мне нужны все разрешения. Думал, что нашел решение с inodes, но не могу найти способ их прочитать (с помощью встроенных функций!).

Только bash, пожалуйста. Любая версия и/или формат допустимы.

редактировать:

Я знаю, что существует множество способов сделать это с помощью внешних команд (stat, ls и т.д.), это просто мыслительный эксперимент — мне не обязательно решать задачу, используя только builtin.

редактировать2:

Ответ Гленна Джэкмана с загружаемыми командами технически верен, так как он использует встроенную команду. Однако, думаю, это просто показывает, что мой вопрос был плохо сформулирован.

Используя чистые bash (любая версия) builtin команды, как перечислено в мануале, и другие встроенные функции bash (перенаправление, замена, ключевые слова, и другие функции, о которых я даже не знаю…), на linux системе, как я могу отобразить полные разрешения файла? Вывод будет похож на любой из приведенных ниже, хотя значение umask тоже подойдет.

user@hostname$ stat test -c %A
-rw-rw-r--

user@hostname$ stat test -c %a
664

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

myperms() {
  local file=$1
  local perms=""
  if [[ -d $file ]]; then
    perms+='d'
  elif [[ -L $file ]]; then
    perms+='l'
  else
    perms+='-'
  fi
  [[ -r $file ]] && perms+='r' || perms+='-'
  [[ -w $file ]] && perms+='w' || perms+='-'
  [[ -x $file ]] && perms+='x' || perms+='-'
  echo "$perms $file"
}

Тогда:

$ myperms /bin/bash
-r-x /bin/bash
$ touch afile
$ myperms afile
-rw- afile
$ chmod u+x afile
$ myperms afile
-rwx afile
$ ln -s afile alink
$ myperms alink
lrwx alink
$ chmod u-wx afile
$ myperms alink
lr-- alink

$ ls -l afile alink
-r--r--r-- 1 glennjackman staff 0 Dec 16 14:28 afile
lrwxr-xr-x 1 glennjackman staff 5 Dec 16 14:29 alink -> afile

С bash версии 5 существуют “загружаемые команды” — команды, которые не являются встроенными командами bash, но могут быть включены, чтобы стать встроенными:

  1. клонируйте репозиторий bash с git: https://savannah.gnu.org/git/?group=bash
  2. ./configure --prefix=/путь/где/вы/хотите/его/установить
  3. make && make install
  4. stat не является “поддерживаемым” загружаемым, даже если он здесь существует, так что
    1. cd ./examples/loadables
    2. make others
    3. cp stat /путь/где/вы/хотите/его/установить/lib/bash

Тогда

  1. Запустите bash shell: /путь/где/вы/хотите/его/установить/bin/bash
  2. установите переменную shell: BASH_LOADABLES=/путь/где/вы/хотите/его/установить/lib/bash
  3. включите команду stat: enable -f stat stat
  4. и используйте ее: stat -A statarray /some/file

stat заполняет ассоциативный массив. Демонстрация (используя массив по умолчанию с именем “STAT”)

$ ~/bash/5.0/bin/bash

$ echo $BASH_LOADABLES_PATH
/Users/glennjackman/bash/5.0/lib/bash

$ enable -f stat stat

$ stat ~/.bashrc

$ declare -p STAT
declare -A STAT=([nlink]="1" https://superuser.com/questions/1510463/builtin-way-to-list-file-permissions-in-linux="/Users/glennjackman/.bashrc" [perms]="0644" [inode]="14482796" [blksize]="4096" [device]="16777220" [atime]="1574454147" [type]="-" [blocks]="8" [uid]="502" [size]="2767" [rdev]="0" [name]="/Users/glennjackman/.bashrc" [mtime]="1574454147" [ctime]="1574454147" [gid]="20" )

$ for key in "${!STAT[@]}"; do printf "%s\t%s\n" "$key" "${STAT[$key]}"; done
nlink   1
link    /Users/glennjackman/.bashrc
perms   0644
inode   14482796
blksize 4096
device  16777220
atime   1574454147
type    -
blocks  8
uid 502
size    2767
rdev    0
name    /Users/glennjackman/.bashrc
mtime   1574454147
ctime   1574454147
gid 20

Чтобы автоматически установить переменную BASH_LOADABLE_PATH, я добавил в свой ~/.bashrc:

# для встроенных загружаемых
bash_root=${BASH%/bin/bash}
[[ -d "$bash_root/lib/bash" ]] && BASH_LOADABLES_PATH="$bash_root/lib/bash"
unset bash_root

Последние абзацы относятся к оригинальному посту, но они имеют смысл только после обсуждения встроенных команд, особенно тех, которые не загружаются по умолчанию.

Переменная BASH_LOADABLES_PATH – это переменная Bash, которая не является env переменной, поэтому вы могли ее пропустить, если не заметили в man-странице Bash. Как и ожидалось, она сообщает Bash, где искать встроенные команды.

На моей системе Debian, из нескольких путей в BASH_LOADABLES_PATH существовал только /usr/lib/bash, прежде чем я создал свой собственный. Согласно info bash, значение по умолчанию (для BASH_LOADABLES_PATH) зависит от системы, так что, возможно, не полагайтесь на /usr/lib/bash. Но не устанавливайте/перезаписывайте BASH_LOADABLES_PATH, лучше размещайте новые встроенные команды в подходящем пути, найденном в BASH_LOADABLES_PATH. Я создал /usr/local/lib/bash, который уже был в BASH_LOADABLES_PATH, затем поместил туда свои встроенные команды Bash.

На моей системе есть несколько команд в директории /usr/lib/bash, кроме stat, некоторые из которых не представлены в /usr/bin. Эти команды могут быть доступны только при включении, и без man-файлов аргумент help – это их единственная документация.

Нет необходимости в аргументе -f для библиотек общих объектов, найденных в директориях BASH_LOADABLES_PATH.

Относительно оригинального поста:

Существует встроенная команда stat, которая работает иначе, чем команда stat. Я не знаю, есть ли она на каждой системе (вопрос о том, гарантировано ли ее наличие, и привел меня к этой теме), но попробуйте включить ее, а затем получите помощь.

$ enable stat
$ help stat

Встроенная stat является оберткой над функцией stat из glibc. Обратитесь к man 3type stat, чтобы узнать, какую информацию раскрывает встроенная stat, или вы можете просто перебрать ключи ассоциативного массива.

К сожалению, встроенная stat не раскрывает разрешения. Однако, если она доступна на вашей системе, включите и получите помощь по встроенной finfo, чтобы узнать ее возможности. Опции -o и -p функции finfo возвращают разрешения в восьмеричном и ASCII форматах, соответственно. Опция -U возвращает имя пользователя, а -G — группу пользователя.

.

Ответ или решение

При поиске способа вывести права доступа к файлу в Linux с использованием исключительно встроенных команд Bash, стоит учитывать ограничения этого подхода. Встроенные команды, такие как test, действительно могут определять права только для владельца файла, и, к сожалению, нет прямого способа в чистом Bash получить полные права доступа к файлу (относительно всех пользователей) без использования внешних утилит вроде ls или stat. Тем не менее, есть несколько подходов, которые могут быть полезны для достижения этой цели в рамках интеллектуального упражнения.

Использование встроенных команд Bash для определения прав текущего пользователя:

Функция Bash, представленная ниже, позволяет вам определить права доступа для текущего пользователя к заданному файлу:

myperms() {
  local file=$1
  local perms=""
  if [[ -d $file ]]; then
    perms+='d'
  elif [[ -L $file ]]; then
    perms+='l'
  else
    perms+='-'
  fi
  [[ -r $file ]] && perms+='r' || perms+='-'
  [[ -w $file ]] && perms+='w' || perms+='-'
  [[ -x $file ]] && perms+='x' || perms+='-'
  echo "$perms $file"
}

Этот скрипт позволяет определить, какие права доступа у текущего пользователя к указанному файлу, и отличается тем, что не требует использования каких-либо внешних команд.

Использование загружаемых команд в Bash версии 5:

В версии 5 Bash появились "загружаемые команды". Эти команды, хоть и не встроены по умолчанию, могут быть добавлены в среду Bash, что превращает их в своего рода встроенные команды. Вот шаги для их настройки:

  1. Клонируйте Bash git-репозиторий: Git Repository.
  2. Настройте и установите Bash в необходимую директорию:
    ./configure --prefix=/path/where/you/want/it/installed
    make && make install
  3. Загрузите необходимые команды. Например, для stat, который тут выступает как загружаемое расширение:
    cd ./examples/loadables
    make others
    cp stat /path/where/you/want/it/installed/lib/bash

После установки откройте новый Bash-сеанс и выполните следующие команды:

  1. Установите переменную BASH_LOADABLES для указания пути к загрузке:
    BASH_LOADABLES=/path/where/you/want/it/installed/lib/bash
  2. Включите команду stat:
    enable -f stat stat
  3. Используйте ее для получения информации о файле:
    stat -A statarray /some/file

Эти шаги позволяют использовать команду stat, которая возвращает массив с различной информацией о файле, включая права доступа в числовом формате.

Заключение

Даже если цель использования только встроенных команд Bash может быть ограничительна, использование загружаемых расширений предоставляет некоторые дополнительные возможности. Это решение позволяет глубже понять архитектуру Bash и способы работы с различными расширениями в Unix-системах. В контексте модернизации процесса часто бывает целесообразно использовать стандартные утилиты Linux, чтобы повысить эффективность и точность.

Оцените материал
Добавить комментарий

Капча загружается...