Encuentre el propietario de un directorio o archivo, pero solo devuelva eso y nada más

62

Estoy buscando un comando que devolverá al propietario de un directorio y solo eso, como una expresión regular que analiza el ls -latcomando o algo similar. Quiero usar el resultado en otro script.

Jason
fuente

Respuestas:

102

stat de GNU coreutils puede hacer esto:

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

Desafortunadamente, hay varias versiones de stat, y no hay mucha consistencia en su sintaxis. Por ejemplo, en FreeBSD, sería

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

Si la portabilidad es una preocupación, probablemente sea mejor usar la sugerencia de Gilles de combinar lsy awk. Tiene que iniciar dos procesos en lugar de uno, pero tiene la ventaja de usar solo la funcionalidad estándar POSIX:

ls -ld /path/of/file/or/directory | awk '{print $3}'
cjm
fuente
2
stat -c% U / ruta, si la brevedad es una bonificación.
tsvallender
1
Eso supone la estadística GNU, que no es el caso en los sistemas Linux más antiguos (incluso en los sistemas más nuevos, sería cauteloso, podría haber un diferente stat(un estándar de todo el sitio) en /usr/local/bino en algún lugar de la casa del usuario), y rara vez está disponible en otras unidades.
Gilles 'SO- deja de ser malvado'
1
stat -c %Utiene la ventaja de trabajar también con BusyBox , si el statcomando está compilado.
Gilles 'SO- deja de ser malvado'
1
Bien, el último ejemplo (ls) funciona tanto en Unix / OSX como en Linux
kenorb
1
Tenga en cuenta que ls imprimirá el uid si no hay un usuario local que coincida con el propietario (es decir, en un recurso compartido de red), pero stat -c '%U' DIRimprimirá UNKNOWN, lo que es menos útil o más apropiado, dependiendo de cómo lo mire.
basic6
18

Analizar la salida de lsrara vez es una buena idea , pero obtener los primeros campos es una excepción, en realidad funciona en todos los dispositivos "tradicionales" (no funciona en plataformas como algunas implementaciones de Windows que permiten espacios en los nombres de usuario).

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

Otra opción es usar un statcomando, pero el problema con statel shell es que hay varios comandos con una sintaxis diferente, por lo que staten un script de shell no es portátil (incluso en instalaciones de Linux).

Tenga en cuenta que probar si un usuario determinado es el propietario es una propuesta diferente.

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
Gilles 'SO- deja de ser malvado'
fuente
Hay algunas advertencias con el ls | awkenfoque también, lamentablemente, como he señalado aquí . Todavía no he encontrado una solución para el problema "el archivo / directorio de destino es un enlace simbólico con un nombre diferente" que mencioné en mi comentario reciente.
beporter
En lugar de find . -user "$username" -print -prune -o -pruneque pudieras simplemente hacerfind . -maxdepth 0 -user "$username"
Niklas Holm
@Gilles ¿Hay alguna razón que uses en awk 'NR==1 {print $3}'lugar de solo awk '{print $3}'? No estoy seguro de por qué NR==1es necesario aquí.
Harold Fischer
1
@HaroldFischer Solo en un caso de borde donde la ruta contiene una nueva línea. Raramente es necesario, pero nunca es dañino.
Gilles 'SO- deja de ser malvado'
@Gilles Muy bueno saberlo !! Solo por curiosidad, ¿conoce una implementación de lsdónde una nueva línea en una ruta hace que la línea se divida en dos (que creo que es el caso límite que está tratando de cubrir)? En GNU ls(versión nueva), BusyBox lsy FreeBSD lsse devuelve una nueva línea como $'\n', ?y ?, respectivamente.
Harold Fischer
9

También se puede hacer esto con GNU find:

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

Esto no es portátil fuera del sistema GNU, pero me sorprendería encontrar una distribución de Linux donde no funcione.

mattdm
fuente
1
Esto funciona en todos los sistemas Linux no integrados y algunos otros (por ejemplo, Cygwin). Es probable que los sistemas integrados tengan Busybox , findque no tiene -printf.
Gilles 'SO- deja de ser malvado'
Como dije, sistema GNU.
mattdm
Los sistemas sin GNU coreutils (como FreeBSD) no tienen -printf:-(.
pevik
@pevik Sí, como dije, aún. Pero puede instalar GNU find si lo necesita. :)
mattdm
@mattdm: no siempre :-(. Lo más importante cuando escribe scripts que deberían ser portátiles.
Pevik
2

En pure bash puedes convertir la salida de lsa una matriz e indexarla.

# (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

No es tan elegante como el uso stat, findo awk, pero podría trabajar en un apuro.

codehearts
fuente