Найти владельца каталога или файла, но только вернуть это и ничего больше

62

Я ищу команду, которая будет возвращать владельца каталога и только это - например, регулярное выражение для разбора ls -latкоманды или что-то подобное? Я хочу использовать результат в другом скрипте.

Джейсон
источник

Ответы:

102

stat из GNU coreutils может сделать это:

stat -c '%U' /path/of/file/or/directory

К сожалению, существует несколько версий stat, и в их синтаксисе нет большой последовательности. Например, во FreeBSD это было бы

stat -f '%Su' /path/of/file/or/directory

Если переносимость является проблемой, вам, вероятно, лучше воспользоваться предложением Жиля о комбинировании lsи awk. Он должен запускать два процесса вместо одного, но он имеет преимущество в использовании только стандартных функций POSIX:

ls -ld /path/of/file/or/directory | awk '{print $3}'
CJM
источник
2
stat -c% U / путь, если краткость является бонусом.
Цваллендер
1
Это предполагает использование GNU stat, чего нельзя сказать о старых системах Linux (даже в более новых системах, я бы с осторожностью отнесся к этому (могут быть другие стандарты statдля всего сайта) в /usr/local/binдоме пользователя или где-то в нем), и он редко доступен на других отделениях.
Жиль "ТАК - перестань быть злым"
1
stat -c %Uимеет преимущество также работает с BusyBox , если statкоманда компиляции.
Жиль «SO- перестать быть злом»
1
Хорошо, последний пример (ls) работает как на Unix / OSX, так и на Linux
kenorb
1
Обратите внимание, что ls напечатает uid, если нет локального пользователя, соответствующего владельцу (т. Е. На общем сетевом ресурсе), но stat -c '%U' DIRнапечатает UNKNOWN, что менее полезно или более уместно, в зависимости от того, как вы на это смотрите.
basic6
18

Анализ выходных данных lsредко является хорошей идеей , но получение первых нескольких полей является исключением, оно фактически работает на всех «традиционных» единицах (оно не работает на платформах, таких как некоторые реализации Windows, которые допускают пробелы в именах пользователей).

ls -ld /path/to/directory | awk 'NR==1 {print $3}'

Другой вариант - использовать statкоманду, но проблема с statоболочкой заключается в том, что существует несколько команд с разным синтаксисом, поэтому statсценарий оболочки непереносим (даже в установках Linux).

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

if [ -n "$(find . -user "$username" -print -prune -o -prune)" ]; then
  echo "The current directory is owned by $username."
fi
if [ -n "$(find . -user "$(id -u)" -print -prune -o -prune)" ]; then
  echo "The current directory is owned by the current user."
fi
Жиль "ТАК - перестань быть злым"
источник
К ls | awkсожалению, есть некоторые предостережения с подходом, как я уже отмечал здесь . Я еще не нашел решение проблемы "target file / dir - это символическая ссылка с другим именем", о которой я упоминал в своем недавнем комментарии.
бипортёр
Вместо того, чтобы find . -user "$username" -print -prune -o -pruneвы могли просто сделатьfind . -maxdepth 0 -user "$username"
Никлас Холм
@ Жиль Есть ли какая-то причина, которую вы используете awk 'NR==1 {print $3}'вместо просто awk '{print $3}'? Я не уверен, почему NR==1это необходимо здесь.
Гарольд Фишер
1
@HaroldFischer Только в случае ребра, где путь содержит новую строку. Это редко необходимо, но никогда не вредно.
Жиль "ТАК - прекрати быть злым"
@ Жиль Очень приятно знать !! Просто любопытно, знаете ли вы о реализации того, lsгде новая строка в пути приводит к тому, что линия разделяется на две части (что, я считаю, является крайним случаем, который вы пытаетесь охватить)? На GNU ls(версия) довольно новый, BusyBox lsи FreeBSD lsновой строки возвращается как $'\n', ?и ?, соответственно.
Гарольд Фишер
9

Это также можно сделать с помощью GNU find:

find $directoryname -maxdepth 0 -printf '%u\n'

Это не переносимо за пределы системы GNU, но я был бы удивлен, обнаружив дистрибутив Linux, где он не работает.

mattdm
источник
1
Это работает на любой не встроенной системе Linux и некоторых других (например, Cygwin). Встраиваемые системы, скорее всего, имеют Busybox , которого findнет -printf.
Жиль "ТАК ... перестать быть злым"
Как я уже сказал, система GNU.
Матдм
Системы без ядра GNU (такие как FreeBSD) не имеют -printf:-(.
pevik
@pevik Да, как я уже сказал. Но вы можете установить GNU find, если вам это нужно. :)
mattdm
@mattdm: не всегда :-(. самое главное, когда вы пишете сценарии, которые должны быть переносимыми.
pevik
2

В чистом bash вы можете преобразовать выходные данные lsв массив и индексировать в него.

# (lrwxr-xr-x, 1, myuser, staff, 36, Oct, 21, 16:36, /path/to/file)    
file_meta=($(ls -ld /path/to/file))
file_owner="${file_meta[2]}" # myuser

Это не так элегантно, как использование stat, findили awk, но может работать в крайнем случае.

codehearts
источник