Trova il proprietario di una directory o di un file, ma restituiscilo solo e nient'altro


62

Sto cercando un comando che restituirà il proprietario di una directory e solo quello - come una regex che analizza il ls -latcomando o qualcosa di simile? Voglio usare il risultato in un altro script.

Risposte:


102

stat dai coreutils GNU può fare questo:

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

Sfortunatamente, ci sono un certo numero di versioni di stat, e non c'è molta coerenza nella loro sintassi. Ad esempio, su FreeBSD, lo sarebbe

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

Se la portabilità è una preoccupazione, probabilmente stai meglio usando il suggerimento di Gilles di combinare lse awk. Deve avviare due processi anziché uno, ma ha il vantaggio di utilizzare solo la funzionalità standard POSIX:

ls -ld /path/of/file/or/directory | awk '{print $3}'

2
stat -c% U / path, se la brevità è un bonus.
Tsvallender,

1
Ciò presuppone stat GNU, che non è il caso dei sistemi Linux più vecchi (anche su sistemi più recenti sarei diffidente, potrebbe esserci un diverso stat(uno standard a livello di sito) in /usr/local/bino da qualche parte nella casa dell'utente), ed è raramente disponibile su altri unices.
Gilles 'SO- smetti di essere malvagio' il

1
stat -c %Uha il vantaggio di lavorare anche con BusyBox , se il statcomando è compilato.
SO di Gilles

1
Bene, l'ultimo esempio (ls) funziona sia su Unix / OSX che su Linux
kenorb,

1
Nota che ls stamperà l'UID se non c'è nessun utente locale corrispondente al proprietario (cioè su una condivisione di rete), ma stat -c '%U' DIRstamperà UNKNOWN, che è meno utile o più appropriato, a seconda di come lo guardi.
basic6

18

Analizzare l'output di lsraramente è una buona idea , ma ottenere i primi campi è un'eccezione, in realtà funziona su tutti gli unices "tradizionali" (non funziona su piattaforme come alcune implementazioni di Windows che consentono spazi nei nomi degli utenti).

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

Un'altra opzione è quella di utilizzare un statcomando, ma il problema con statla shell è che ci sono più comandi con sintassi diversa, quindi statin uno script di shell è insostenibile (anche attraverso installazioni Linux).

Tieni presente che verificare se un determinato utente è il proprietario è una proposta diversa.

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 | awkSfortunatamente ci sono alcuni avvertimenti con l' approccio, come ho notato qui . Non ho ancora trovato una soluzione per "problema / file target è un link simbolico con un nome diverso", che ho citato nel mio recente commento.
Beporter,

Invece di find . -user "$username" -print -prune -o -prunete potresti semplicemente farefind . -maxdepth 0 -user "$username"
Niklas Holm il

@Gilles C'è qualche motivo che usi awk 'NR==1 {print $3}'invece di solo awk '{print $3}'? Non sono sicuro del motivo per cui NR==1è necessario qui.
Harold Fischer,

1
@HaroldFischer Solo in un caso limite in cui il percorso contiene una nuova riga. È raramente necessario, ma mai dannoso.
Gilles 'SO- smetti di essere malvagio' il

@Gilles Molto buono a sapersi !! Solo curioso, sei a conoscenza di un'implementazione di lsdove una nuova riga in un percorso provoca la divisione della linea in due (che credo sia il caso limite che stai cercando di coprire)? Su GNU ls(nuova versione), BusyBox lse FreeBSD lsviene restituita una nuova riga come $'\n', ?e ?, rispettivamente.
Harold Fischer,

9

Si può anche fare questo con GNU find:

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

Questo non è portatile al di fuori del sistema GNU, ma sarei sorpreso di trovare una distribuzione Linux dove non funziona.


1
Funziona su ogni sistema Linux non incorporato e pochi altri (ad es. Cygwin). È probabile che i sistemi integrati dispongano di Busybox , di cui findnon dispone -printf.
Gilles 'SO- smetti di essere malvagio' il

Come ho detto, sistema GNU.
Mattdm,

I sistemi senza coreutils GNU (come FreeBSD) non hanno -printf:-(.
pevik

@pevik Sì, come ho detto, ancora. Ma puoi installare GNU find se ne hai bisogno. :)
mattdm,

@mattdm: non sempre :-(. soprattutto quando scrivi script che dovrebbero essere portatili.
pevik

2

In pure bash è possibile convertire l'output di lsin un array e indicizzarlo in esso.

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

Non è elegante come utilizzando stat, findo awk, ma potrebbe funzionare in un pizzico.

Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.