Przenoszenie milionów plików do innego katalogu ze specyficznymi wzorami nazw


10

Mam miliony plików z następującą nomenklaturą na komputerze z systemem Linux:

1559704165_a1ac6f55fef555ee.jpg

Pierwsze 10 cyfr to znacznik czasu, a następujące po nich _to konkretne identyfikatory. Chcę przenieść wszystkie pliki pasujące do określonych identyfikatorów plików do innego folderu.

Próbowałem tego w katalogu z plikami

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

Jednak pojawia się błąd wskazujący:

bash 1559704165_a1ac6f55fef555ee.jpg: command not found

Kiedy próbowałem, mv ??????????_a1ac*.jpg pojawia się zbyt długi błąd listy argumentów. Mam co najmniej 15 różnych wzorów nazw plików. Jak je przenieść?


1
Bash mówi wszystko: próbuje wykonać tę nazwę pliku, ponieważ jest ona pierwsza w linii w drugim etapie potoku (twoja potoka w drugim etapie to | ??????????_a1ac*.jpg: bash rozwija ją do kilku nazw plików, pierwszą rzeczą jest to 1559704165_a1ac6f55fef555ee.jpg, że skończysz , w tym drugim etapie potoku, próbując wykonać: 1559704165_a1ac6f55fef555ee.jpg next_matching_filename 3rd_matching_filename ... nth_matching_filenameMyślę, że zamiast tego próbowałeś przefiltrować do tej nazwy pliku (zobacz odpowiedzi poniżej)
Olivier Dulac

Odpowiedzi:


15

Powinieneś użyć:

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

Tak więc maxdepth 1środki, które chcesz wyszukać w bieżącym katalogu bez podkatalogów.

type f oznacza znajdź tylko pliki.

name '??????????_a1ac*.jpg' to wzorzec pasujący do szukanego pliku.

mv -t destination "{}" +oznacza przeniesienie dopasowanych plików do miejsca docelowego. Tutaj +dodaje nowe dopasowane pliki do poprzedniego, takie jak:

mv -t dest a b c d

Tutaj abcd to różne pliki.


Dziękujemy za zwięzłe udzielenie odpowiedzi na pytanie tej osoby. Zamiast po prostu zrzucić rozwiązanie, może mógłbyś wyjaśnić, jak / co / dlaczego. Zamiast być użytecznym dla jednej osoby, raz, może być przydatna dla wszystkich przez cały czas. To samo pytanie zostało zadane i udzielono odpowiedzi niezliczoną ilość razy w ciągu ostatnich 40-50 lat. Problem polega na tym, że nigdy nie zostało to dobrze wyjaśnione. Naucz człowieka łowić ryby. Tymczasem: gnu.org/software/findutils/manual/html_node/find_html/... i jak to często bywa, Wikipedia jest bardziej przydatna niż oficjalne dokumenty: en.wikipedia.org/wiki/Find_ ( Unix)
głosy

Zobacz zaktualizowaną odpowiedź.
Prvt_Yadav

Zauważ, że -tjest to rozszerzenie GNU, więc może nie być dostępne w innych typach pochodnych UNIX.
Kevin

Kiedy mówisz „Podwójne cudzysłowy zapobiega dzieleniu słów”. Zakładam, że masz na myśli "{}", w którym to przypadku chcę podkreślić, że {}nie jest on rozszerzany przez powłokę i nie trzeba go cytować. Powłoka przechodzi, {}by znaleźć i znaleźć, widzi {}i zastępuje ją ścieżkami. Find exec nie używa parsera powłoki i nie dokonuje własnego podziału słów. Cytując, nie wyrządza to żadnej szkody, po prostu podane uzasadnienie jest nieco niedokładne.
jw013,

@ jw013 dzięki.
Prvt_Yadav

11

Twoje rozkaz

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

Przerzuca listę wszystkich plików DO wszystkich plików!

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

da rade.


1
wielkie dzięki ... twoje rozwiązanie też zadziałało ... dziękuję za poinformowanie mnie, gdzie popełniłem błąd
Apricot

8

Jesteś bardzo blisko. Powinieneś użyć -nameopcji do find. I pamiętaj, aby zacytować wzór.

Więc

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

Wielkie dzięki ... twoje rozwiązanie również zadziałało ... dodatkowe podziękowania za poinformowanie mnie, że byłem blisko rozwiązania ... jest to motywacja dla nowicjusza takiego jak ja
Apricot

1
powinieneś dodać -print0jako ostatni argument do find (zamiast domyślnego: -print) i dodać -0jako pierwszą opcję do xargs (tj xargs -0 mv -t "/home/ubuntu/ntest". :) . w ten sposób można obsłużyć wszelkiego rodzaju dziwne nazwy plików (ze spacjami, „newline” itp.). find . -maxdepth 1 -type f -name '??????????_a1ac*.jpg' -print0 |xargs -0 mv -t "/home/ubuntu/ntest" (działa tylko z znalezieniem podobnym do GNU)
Olivier Dulac

2

Nie tak „dobre” jak findrozwiązania, ale innym prawidłowym rozwiązaniem jest mvzwiększenie szczegółowości poleceń.

Robi to 4096 ruchów, przy mniejszej liczbie plików przenoszonych na mvoperację.

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

To sprytny hack dla osób bez find(z jakiegokolwiek powodu).
las

-1

Jeśli chcesz przenieść pliki na ten sam system hosta, co, jak sądzę, robisz ze swoim mv, rsyncmoże być szybszą opcją:

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

--inplacei -Wsą ustawione na przyspieszenie procesu.

Jeśli to spowoduje, że kolejny argument listy będzie zbyt długi, możesz podać listęrsync

Utwórz listę za pomocą na przykład find

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

i daj to rsync

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

Oto źródło /path/to/files, ponieważ rsyncpotraktuje podaną przez ciebie listę w stosunku do twojego źródła.


Chodzi o to, że: rsyncjest szybszy niż mv, jeśli pliki nie są w tym samym systemie plików .


Prawdopodobnie trafi ten sam błąd „zbyt długiej listy argumentów”, o którym wspominał OP
Grump

@ Grump, aby tego uniknąć, OP mógłby zapisać listę plików do skopiowania do pliku, tj. find . -maxdepth 1 -type f -name '??????????_a1ac*.jpg' > /tmp/my_image_list.txtA następnie przekazać ją do rsync --files-from=/tmp/my_image_list.txt. Chodzi o to, że rsyncjest szybszy. Chyba że pliki znajdują się w tym samym systemie plików, czego OP nie wskazał.
Robert Riedl

@RobertRiedl: powinieneś edytować swoją odpowiedź i dodać tę informację. Komentarze mogą być nietrwałe.
NickD

@NickD, zaktualizowałem swoją odpowiedź.
Robert Riedl,
Korzystając z naszej strony potwierdzasz, że przeczytałeś(-aś) i rozumiesz nasze zasady używania plików cookie i zasady ochrony prywatności.
Licensed under cc by-sa 3.0 with attribution required.