Come posso padroneggiare il comando find UNIX?


11

Penso di essere abbastanza avanzato nel mio uso di find ma ogni volta che lo uso non riesco a ricordare per la vita il metodo per chiudere l'opzione -exec. Trascorro molto tempo a leggere ogni volta che lo uso. Non sto semplicemente usando abbastanza o non mi aspetto troppo da me stesso? Cominciamo con un esempio tipico che mi rende frustrato.

La struttura delle directory ha file con tutte le autorizzazioni errate, file nascosti, collegamenti simbolici, ecc. Voglio cambiare la proprietà a un valore ragionevole

find . -type f -exec chown username {} \;
find . -type d -exec chown username {} \;
find . -type d -exec chgrp usergroup {} \;
find . -type f -exec chgrp usergroup {} \;

(Scusami se il finale è all'indietro ... L'ho guardato un'ora fa e ancora non sono sicuro)

Ma ho paura di eseguirlo a causa di montature, collegamenti simbolici, ecc. Ho fatto il goof supremo di chmod. * E l'avevo fatto ricorrere su di me prima. So -xdev rinuncerà alle partizioni incrociate ma non sono sicuro di cosa accadrà ai file che vivono all'interno delle directory che sono collegamenti simbolici.

Quindi, come si fa a dominare questa bestia che può uccidere file cruciali?

Aggiorna potando i migliori suggerimenti di seguito e riassumendo:

  1. Avere una directory di pratica collegata e montata su altre directory di pratica.
  2. Usa xargs anziché il comando exec non intuitivo.
  3. Utilizzare -exec echo {} per sanità mentale e sicurezza
  4. Il punto e virgola è speciale e lo stai scappando, quindi il carattere di escape è il primo
  5. Il comando -o può aiutarti a combinare i criteri di selezione.

Sono un po 'confuso riguardo a print0 ma xargs è sempre stato un po' sulla pratica non facile da capire a prima vista che cerco di evitare.


1
Non riesco nemmeno a ricordarmelo, quindi lo installo in xargs.
risonatore il

2
Quando sei soddisfatto della creazione del comando giusto, considera di eseguirlo con + invece di \; Funzionerà più velocemente con + perché il comando exec verrà chiamato molto meno spesso.
wzzrd,

wzzrd, ottimo consiglio sull'uso di + anziché \;
Daniel Lawson,

Risposte:


19

Bene, per quanto riguarda la -execsintassi, potresti fare come molte persone, rinunciare e usare xargs:

find . -type f | xargs chown username

(o la versione file-con-spazi-e-altro-non-senso-in-loro-sicuro)

find . -type f -print0 | xargs -0 chown username

Oppure, per cercare di ricordare la cosa giusta da fare con il punto e virgola, quello che devi esaminare nella testa è che stai usando un punto e virgola per terminare il comando in -execesecuzione e devi scappare dal punto e virgola perché ha significato a bash. Ecco perché è un punto e virgola rovesciato. Sembra che la {}parte di sostituzione sia a posto.

Per quanto riguarda l'uccisione di file e così via, se stai eseguendo qualcosa di grosso e pericoloso di cui stai parlando, prima fai questo:

find . -type f -exec echo chown username {} \;

e rivedere i risultati. Questa è fondamentalmente una "corsa a secco" in cui vedrai i comandi che verrebbe eseguito se lo lasciassi. Sicuramente una buona pratica. Non aiuterà con il .*problema, ma sai di non farlo adesso. :)


1
+! per la pratica 'eco' a secco. Lo uso sempre per un grande cambiamento
Steve Folly,

3

Sono sorpreso che nessuno abbia ancora menzionato la seguente opzione:

find . -type f -ok chown username {} \;

Questa sintassi confermerà il comando prima di eseguirlo. Funziona meglio se ti aspetti che la tua partita sia un numero relativamente piccolo di file perché richiederà ciascuno di essi.

Alcune risposte menzionano xargs, ma con GNU anche questo non è necessario:

find . -type f -exec chown username {} \+

Nota che in genere non è necessario sfuggire al +, ma è bene prendere l'abitudine di farlo comunque.


Puoi spiegare la natura del segno più ... cosa sta facendo esattamente? La shell lo sta elaborando o il comando? Penso che scaricherò il codice sorgente per gnu-find perché questo è un argomento interessante.
ojblass,

find lo sta elaborando. Leggi man find per saperne di più su quell'opzione.
Kamil Kisiel,

3

Ecco a cosa serve l'uomo: può essere difficile ricordare le cose, ecco perché il comando * nix include le pagine man. Si può solo controllare sempre la sezione Azione della pagina man per un promemoria sulla sintassi: man find. Sebbene le pagine man possano sembrare non amichevoli, una volta che sei bravo a leggerle sono molto utili.

Crea un front-end o un wrapper: quando volevo migliorare su GNU find, ho scritto un front-end della GUI per find che genera comandi find con python, glade e pygtk. Questo è un buon esercizio se vuoi conoscerlo davvero bene.

Avere una directory di pratica: Infine, ho sempre una directory 'scrap' nella mia home directory per giocare con comandi potenti quando qualcosa come 'echo' non la taglia. Puoi usare l'espansione della shell per creare rapidamente un mucchio di file con qualcosa del tipo:

for i in {1..100}; do touch "$i"; done

Strano una directory di pratica è qualcosa che non ho mai considerato.
ojblass,

1

È inoltre possibile combinare le espressioni find con gli operatori '-and' e '-or'. -e è implicito:

find . -type f -name "plainfile" ...

equivale a

find . -type f -and -name "plainfile" ...

L'operatore o può ridurre a 2 il tuo elenco di 4 comandi:

find . -type d -or -type f ...

E infine, non legato alla ricerca, ma anche chown può impostare anche il gruppo. Quindi, affrontando anche gli spazi nei nomi finiamo con:

find . -type d -or -type f -exec chown username:usergroup '{}' \;

Cosa trovi con il business o. [Sic]
ojblass,

@ojblass: find combina le espressioni usando 'e' o 'o', per impostazione predefinita se non vengono specificati né '-e' né '-o', '-e' viene usato implicitamente. Quindi digitare 'find -type d -type f' non troverà nulla perché nulla è una directory e un file.
Steve Folly,

0

Alla chiusura penso solo di usare; come con molti linguaggi di programmazione e poi fuggire. Ricorda solo che è necessario sfuggire e ti arriva abbastanza facilmente.


0

A seconda della versione di find che stai utilizzando ci sono diverse opzioni che potrebbero aiutarti. GNU find è probabilmente il più potente e questo può aiutarti con la tua seconda domanda (implicita)

Ad esempio: il comportamento predefinito non è quello di dereferenziare i collegamenti simbolici, ma è possibile ignorarlo; e l'opzione -mount non trova più i punti di mount

Cerca nelle pagine man locali


0

Alcuni sosterrebbero che l'opzione xargs è più veloce dell'opzione -exec perché non eseguirà il comando una volta per ogni file, ma non mi preoccuperei di questo per qualsiasi cosa tranne i lavori di massa che richiedono una quantità non banale di tempo.

Personalmente, di solito corro a trovare senza exec

find /path/to/dir -name whatever

assicurati che l'output appaia corretto, quindi esegui il mio comando su quell'elenco.

chown user:group `find /path/to/dir -name whatever`

Esempio perfetto di come "non" fare le cose. Nomi di file con spazi.
Ian Kelling,

Sì, questo è un potenziale problema che forse avrei dovuto riconoscere. Tuttavia, il mio punto era leggere l'output find prima di eseguire qualsiasi cosa, in cui si sarebbero individuati spazi o altra follia di nomi di file.
theotherreceive il

0

Per alcune shell (non bash) scappare {} per un comportamento corretto.

\{\} or '{}'

find manual è buono per il mastering find.


No non lo fai; find funziona alla perfezione con {} così come sono. Fanno parte del comando find: sono un token che viene sostituito dal risultato del comando find. Significano qualcosa in bash solo quando si definiscono funzioni o si chiamano variabili, quindi è possibile utilizzarle come nella domanda originale.
wzzrd,

È dalla pagina man. Ho aggiornato per dire che non è applicabile a Bash.
Ian Kelling il

0

Prima di fare qualcosa del genere, assicurati che la directory in cui stai eseguendo questo comando non sia nello stesso filesystem di / usr o / etc. (altrimenti se ho un hard link a / etc / passwd o a / bin / sh nella mia home directory mi hai appena dato la proprietà di quelli e come effetto collaterale ora possiedo la macchina).

Se si desidera ricorrere attraverso una directory e chown tutti i file / directory, un semplice

chown -Rh user: usergroup user /

lo farà. Assicurarsi Assicurarsi di utilizzare il -h o chown sarà seguire i link simbolici.


Non penso che questo sia multipiattaforma. Inoltre fallisce con 247K di file, come dimostrato dal mio ambiente di pratica. Non sono sicuro del perché.
ojblass,

Penso che tu abbia trovato un bug più di quanto tu abbia riscontrato un problema di multipiattaforma. Quale versione e qual è lo stato di uscita in caso di errore? Per quanto ne so, è nato dapprima nelle prime versioni di bsd; è sicuramente in sunos 5.3 e ultrix e irix. Quanti ne elabora prima di fallire?
chris,

Hai ragione, funziona su AIX 5.3, AIX 5.2, ma non su AIX 4.3, NCR, HP 11, HP 10.20 o sulle mie distribuzioni DSL. IN tutti i casi sembra non riuscire a file vicini o vicini a 60k.
ojblass,
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.