Rimuovere il percorso dall'output del comando find


29

Ho uno script bash per distribuire il codice da un ambiente beta a un ambiente di produzione, ma attualmente devo aggiungere manualmente l'elenco dei file a un file txt e qualche volta mi manca un po '. Fondamentalmente il mio script di distribuzione cat / loop copia i file. (esporta / importa anche db ma non è rilevante..lol)

Ad ogni modo, vorrei usare il findcomando per generare un elenco di file modificati negli ultimi 14 giorni. Il problema è che devo eliminare il percorso ./affinché lo script di distribuzione funzioni.

Ecco un esempio dell'uso del comando find:

trova . -type f -mtime -14> deploy.txt

Ecco la linea che i gatti deploy.txtnel mio script di distribuzione:

for i in `cat deploy.txt`; do cp -i /home/user/beta/public_html/$i /home/user/public_html/$i; done

Qualche idea su come realizzare ciò usando lo script bash?

Grazie!


3
C'è un motivo per cui non puoi semplicemente usare rsync per questo? Sembra che tu stia provando a reinventare la ruota e renderla un triangolo.
ThatGraemeGuy

punto valido tuttavia prima della distribuzione viene esaminato deploy.txt e tutto ciò che deve essere riparato viene rimosso
Mikey1980,

1
Forse esegui rsync in --dry-runmodalità e l'output in un file per la revisione?
Zoredache,

Risposte:


36

È possibile utilizzare l' -printfopzione della riga di comando con %fper stampare solo il nome file senza alcuna informazione sulla directory

find . -type f -mtime -14 -printf '%f\n' > deploy.txt

oppure puoi usare sed per rimuovere semplicemente ./

find . -type f -mtime -14 | sed 's|^./||' >deploy.txt

Credo che tu debba sfuggire al /..
SEE

5
Non quando lo usi |come delimitatore.
user9517 supporta GoFundMonica il

3
L'uso %feliminerà tutte le directory, non solo ./. Ciò interromperà il suo script di distribuzione se uno dei file restituiti findsi trova in sottodirectory.
James Sneeringer,

2
@Iain Devi scappare dal pensiero .. E forse è meglio usare un'ancora di inizio linea:s|^\./||
James O'Gorman il

12
Usa %Pinvece di %f. Questo ha semplicemente interrotto il percorso indicato nella riga di comando.
TrueY

12

Il ./dovrebbe essere innocuo. La maggior parte dei programmi considera /foo/bare /foo/./barcome equivalenti. Mi rendo conto che non sembra molto bello, ma in base a ciò che hai pubblicato, non vedo alcun motivo per cui ciò causerebbe il fallimento del tuo script.

Se vuoi davvero toglierlo, sedè probabilmente il modo più pulito:

find . -type d -mtime 14 | sed -e 's,^\./,,' > deploy.txt

Se sei su un sistema con GNU find (ad esempio la maggior parte dei sistemi Linux), puoi farlo in un colpo solo con find -printf:

find . -type d -mtime 14 -printf "%P\n" > deploy.txt

Le %Prestituisce il percorso completo di ogni file trovati, meno il percorso specificato nella riga di comando, fino ad includere la prima barra. Ciò conserverà tutte le sottodirectory nella struttura della directory.


1
Il ./prefisso è in realtà una funzione; senza di essa, il piping dell'output ad altri comandi non funzionerà correttamente, ad es. per i nomi di file che iniziano con un trattino.
Tripleee,

1
@tripleee - Capisco l'utilità di esso, ma OP ha chiesto in modo specifico come eliminarlo perché stava causando problemi per il suo script di distribuzione. Certo, potrebbero esserci modi migliori per fare ciò che deve fare, ma questa è una tana di coniglio ben oltre lo scopo di ciò che gli è stato chiesto.
James Sneeringer,

7

Perché è necessario rimuovere il ./? È valido avere in un percorso. Così

cp -i dir1/./somefile dir2/./somefile

va bene!

Ma se desideri eliminare il nome della directory in find, puoi usare %Parg per -printf.

man find (1) dice:

         %P     File's name with the name of the  command  line  argument
                 under which it was found removed.

Un esempio

$ find other -maxdepth 1
other
other/CVS
other/bin
other/lib
other/doc
other/gdbinit
$ find other -maxdepth 1 -printf "%P\n"

CVS
bin
lib
doc
gdbinit

Attenzione alla prima riga vuota! Se vuoi evitarlo usa-mindepth 1

$ find other -mindepth 1 -maxdepth 1 -printf "%P\n"
CVS
bin
lib
doc
gdbinit

3

Bene, hai alcune opzioni. È possibile utilizzare l' -printfopzione in find per stampare solo il nome del file, oppure è possibile utilizzare uno strumento come sed per eliminare semplicemente il file ./.

# simply print out the filename, will break if you have sub-directories.
find . -mtime -14 -printf '%f\n'

# strip a leading ./
find .  -mtime -14 | sed -e 's/^\.\///'

Puoi darmi un esempio del suo utilizzo? Siamo spiacenti, Linux non è davvero il mio forté
Mikey1980,

2
Guarda di nuovo, ci sono esempi.
Zoredache,

D'accordo - provalo, non farai del male a nessuno che esegue una combinazione di find e sed.
SEEEA

3

La soluzione "find -printf" non funzionerà su FreeBSD perché find non ha questa opzione. In questo caso AWK può essere d'aiuto. Restituisce un cognome ($ NF), quindi può funzionare a qualsiasi profondità.

find /usr/local/etc/rc.d -type f | awk -F/ '{print $NF}'

PS: tratto dal libro "Programmazione shell Linux e Unix" di D.Tansley


2

Una soluzione rapida, se capisco correttamente la domanda, sta usando cutsull'output del findcomando:

$> find . -type f -mtime -14 | cut -b 3- > deploy.txt

In questo modo il primo verrà rimosso dai caratteri di ciascuna riga del risultato (nel tuo caso ./). Probabilmente non è la soluzione migliore, ma funziona nel tuo scenario.


1

sed è perfetto per questo genere di cose.

$ find . -type f -mtime -14 find . | sed 's/^\.\///' > deploy.txt

1

Non so di che tipo di nomi di file stiamo parlando, ma qualsiasi cosa con spazi o nuove righe mette a rischio la maggior parte delle soluzioni qui.

Il mio suggerimento sarebbe di usare l'espansione dei parametri della shell per rimuovere i caratteri da ciascun nome file:

find . -mtime -14 -exec sh -c 'printf "${0#./}\n"' {} \; >deploy.txt

Se davvero ti piacciono le pipe, potresti usare un delimitatore "sicuro", come un null, con xargs per ricevere ogni nome di file:

find . -mtime -14 -print0 | xargs -0 -n 1 sh -c 'printf "${0#./}\n"' >deploy.txt

Ricorda che l'output di questo NON è delimitato da null, quindi sebbene possa essere sufficiente per un controllo del bulbo oculare, nessuna di queste soluzioni produce un file deploy.txt che è sicuro da usare per l'automazione, a meno che tu non sia molto sicuro della tua fonte i nomi dei file.

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.