Lanciare un comando su tutti i file con un certo nome

Lanciare un comando su tutti i file con un certo nome

Dovete cambiare i diritti di accesso a tutti i file conuna certa estensione, oppure eliminare tutti i file di backup sparsi in giro per il filesystem, o concatenare tutti i file il cui nome segue una certa regola ma che stanno in directory diverse. Sono casi che si presentano spesso, e grazie alla shell, c'è un modo semplice ed efficace per eseguire questi compiti, all'apparenza diffici.

Usare find per cercare un file

In ognuno di quei casi, quello che vogliamo fare è eseguire uno stesso comando su un gruppo di file, identificabili da una caratteristica comune. Il primo step quindi è quello di riuscire a selezionarli.

Il comando find è fatto appositamente per questo: consente di trovare (da cui il nome find) tutti i file nel filesystem date certe regole. Ad esempio con


$ find ./ -name readme.md

otteniamo un elenco di tutti i file o le directory chiamate readme.md nel percorso corrente e in tutte le sottodirectory.

Adesso basterebbe poter eseguire un comando su ognuno di quei file.

Lo switch -exec

Lo switch -exec di find permette di eseguire un comando su ognuno dei file individuati da find. Partiamo con un esempio:


$ find ./ -name readme.md -exec cat {} +

Questo comando esegue cat su tutti i file chiamati readme.md nel percorso corrente e in tutte le directory sottostanti.

Analiziamo la sintassi di quanto passato a -exec: in pratica troviamo il comando da eseguire cat, il gruppo parentesi graffa aperta + parentesi graffa chiusa che rappresenta il nome completo del file identificato da find e il carattere + che segnala al comando la fine del omando da eseguire.

Esiste anche una sintassi alternativa in cui il + è sostituito da ; ma in questo caso occorre far precedere il ; da un backslash in modo che la shell non lo interpreti come separatore da un comando successivo:


$ find ./ -name readme.md -exec cat {} \;

Uso dei wildcards

Supponiamo di voler individuare tutti i file con una certa estensione in un'alberatura di percorsi, e magari di voler eseguire un certo comando su tutti questi files, sarebbe comodo poter usare dei wildcards per poterli identificare. Ovviamente find permette di farlo ed in modo molto comodo.

Vediamo un esempio: supponiamo di voler eliminare tutti i file con estensione .bak da tutte le sottodirectory della directory corrente. Il comando da usare è:


$ find ./ -name '*.bak' -exec rm {} +

Si noti l'utilizzo degli apici singoli intorno a *.bak per impedire alla shell di sostituire questa parte del comando con effettivi nomi di file .bak presenti nella directory corrente.

Altre idee e suggerimenti

Il comando find è molto versatile e potente, ha molti switch che si possono usare per adattarne il funzionamento a tanti casi diversi. Il suggerimento qui è quello di studiarne la pagina man per farsi un'idea di tutto quello che può fare e magari ricordarsene nel momento del bisogno!

Voglio però lasciarvi alcuni esempi che a volte ho trovato utili:

find /etc -type d Elenca tutte e sole le sottodirectory di /etc

find /etc -type l Elenca solo i link simbolici nelle sottodirectory di /etc

find /etc -mtime 15 Elenca i file di /etc che sono stati modificati negli ultimi 15 giorni (intesi come 24*15 ore da adesso)

find /etc -cnewer /etc/hosts Elenca i file di /etc che sono stati modificati successivamente a /etc/hosts

find /etc -type f -executable Elenca i soli file nelle sottocartelle di /etc che l'utente corrente può eseguire

find /etc -type f -empty Elenca solo i file vuoti nelle sottocartelle di /etc

Currently there are no comments, so be the first!