Spostamento di milioni di file in una directory diversa con schemi di nomi specifici


10

Ho milioni di file con la seguente nomenclatura su una macchina Linux:

1559704165_a1ac6f55fef555ee.jpg

Le prime 10 cifre sono timestamp e quelle seguite da a _sono ID specifici. Voglio spostare tutti i file corrispondenti a specifici ID di file in una cartella diversa.

Ho provato questo sulla directory con i file

find . -maxdepth 1 -type f | ??????????_a1ac*.jpg |xargs mv -t "/home/ubuntu/ntest"

Tuttavia sto ricevendo un errore che indica:

bash 1559704165_a1ac6f55fef555ee.jpg: command not found

Quando ho provato, mv ??????????_a1ac*.jpg sto ricevendo errore elenco troppo lungo elenco argomenti. Ho almeno 15 diversi modelli di nome file. Come li sposto.


1
La bash dice tutto: cerca di eseguire quel nome di file in quanto è il primo sulla linea nel 2 ° stadio della pipe (il tuo tubo di 2 ° stadio è | ??????????_a1ac*.jpg:: bash lo espande in diversi nomi di file, il primo è 1559704165_a1ac6f55fef555ee.jpg, si finisce , in quel 2 ° stadio di pipe, cercando di eseguire:. 1559704165_a1ac6f55fef555ee.jpg next_matching_filename 3rd_matching_filename ... nth_matching_filenameImmagino che tu abbia cercato invece di filtrare per quel nome di file (vedi le risposte sotto per quello)
Olivier Dulac

Risposte:


15

Dovresti usare:

find . -maxdepth 1 -type f -name '??????????_a1ac*.jpg' \
-exec mv -t destination "{}" +

Quindi maxdepth 1significa che non si desidera cercare nella directory corrente nessuna sottodirectory.

type f significa trovare solo i file.

name '??????????_a1ac*.jpg' è un modello che corrisponde al file che stai cercando.

mv -t destination "{}" +significa spostare i file corrispondenti a destinazione. Qui +aggiunge nuovi file corrispondenti a quello precedente come:

mv -t dest a b c d

Qui abcd sono file diversi.


Grazie per aver risposto in modo conciso a questa domanda. Invece di scaricare semplicemente una soluzione, forse potresti spiegare come / cosa / perché. Invece di essere utile a una persona, una volta, può essere utile a tutti, sempre. La stessa domanda è stata posta e ha risposto innumerevoli volte negli ultimi 40-50 anni. Il problema è che non è mai stato spiegato bene. Insegna a un uomo a pescare .. Nel frattempo: gnu.org/software/findutils/manual/html_node/find_html/… e come spesso accade Wikipedia è più utile dei documenti ufficiali: en.wikipedia.org/wiki/Find_ ( Unix)
esprime l'

Vedi la risposta aggiornata.
Prvt_Yadav,

Si noti che -tè un'estensione GNU e quindi potrebbe non essere disponibile su altri tipi di derivati ​​UNIX.
Kevin,

Quando dici "Le virgolette doppie impediscono la divisione delle parole". Presumo che ti riferisca "{}", nel qual caso voglio sottolineare che {}non è espanso dalla shell e non ha bisogno di essere citato. La shell passa {}per trovare, trovare trova {}e lo sostituisce con nomi di percorso. Trova exec non usa il parser di shell e non fa alcuna suddivisione delle parole per conto suo. Citarlo non fa alcun danno, è solo che la giustificazione fornita è un po 'imprecisa.
jw013,

@ jw013 grazie.
Prvt_Yadav,

11

Il tuo comando,

find . -maxdepth 1 -type f | ??????????_a1ac*.jpg |xargs mv -t "/home/ubuntu/ntest"

Pipa l'elenco di tutti i file A tutti i file!

find . -maxdepth 1 -type f -name `*_a1ac*.jpg` -print0 |\
xargs  -0 -r mv -t "/home/ubuntu/ntest"

farà il trucco.


1
molte grazie ... anche la tua soluzione ha funzionato ... grazie per avermi fatto sapere dove ho sbagliato
Apricot

8

Sei molto vicino. Dovresti usare l' -nameopzione per find. E ricorda di citare il modello.

Così

find . -maxdepth 1 -type f -name '??????????_a1ac*.jpg' |xargs mv -t "/home/ubuntu/ntest"

Mille grazie ... anche la tua soluzione ha funzionato .... grazie in più per avermi fatto sapere che ero vicino alla soluzione .... è un motivatore per un principiante come me
Apricot

1
dovresti aggiungere a -print0come ultimo argomento alla ricerca (invece del predefinito: -print), e aggiungi a -0come prima opzione a xargs (es .::) xargs -0 mv -t "/home/ubuntu/ntest". in questo modo, tutti i tipi di nomi di file strani (con spazi all'interno, con "newline" all'interno, ecc.) possono essere gestiti. find . -maxdepth 1 -type f -name '??????????_a1ac*.jpg' -print0 |xargs -0 mv -t "/home/ubuntu/ntest" (funziona solo con la ricerca simile a GNU, però)
Olivier Dulac l'

2

Non "buono" come le findsoluzioni, ma un'altra valida soluzione è rendere i mvcomandi più granulari.

Questo fa 4096 mosse, con un numero minore di file spostati per mvoperazione.

FILEPAT=a1ac
for i in $(seq $((0x000)) $((0xfff))); 
do 
   H=$(printf '%x\n' $i)
   mv 1559704165_${FILEPAT}${H}*.jpg /home/ubuntu/ntest
done

Questo è un trucco intelligente per quelli senza find(per qualsiasi motivo).
foresta

-1

Se vuoi spostare i file sullo stesso sistema host, che immagino tu stia facendo con il tuo mv, rsyncpotrebbe essere un'opzione più veloce:

rsync -av --inplace -W /source/??????????_a1ac*.jpg /home/ubuntu/ntest/

--inplacee -Wsono impostati per accelerare il processo.

Se ciò produce un errore troppo lungo di un altro elenco di argomenti, è possibile alimentare gli elenchirsync

Crea l'elenco con find, ad esempio

find . -maxdepth 1 -type f -name '??????????_a1ac*.jpg' > /tmp/my_image_list.txt

e darlo a rsync

rsync -av --inplace -W --files-from=/tmp/my_image_list.txt /path/to/files /home/ubuntu/ntest/

La fonte qui è /path/to/files, perché rsynctratterà la lista che gli dai come relativa alla tua fonte.


Il punto è: rsyncè più veloce di mv, se i file non si trovano sullo stesso filesystem .


È probabile che questo colpisca lo stesso errore "elenco argomenti troppo lungo" menzionato dall'OP
Grump

@Grump, per evitarlo, OP potrebbe scrivere l'elenco di file da copiare in un file, ad es. find . -maxdepth 1 -type f -name '??????????_a1ac*.jpg' > /tmp/my_image_list.txtE poi passarlo a rsync con --files-from=/tmp/my_image_list.txt. Il punto è che rsyncè più veloce. A meno che i file non risiedano sullo stesso filesystem, che OP non ha indicato.
Robert Riedl,

@RobertRiedl: dovresti modificare la tua risposta e aggiungere queste informazioni. I commenti possono essere impermanenti.
NickD,

@NickD, ho aggiornato la mia risposta.
Robert Riedl,
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.