Milyonlarca dosyayı özel ad desenleriyle farklı bir dizine taşıma


10

Bir Linux makinesinde aşağıdaki adlandırmaya sahip milyonlarca dosyam var:

1559704165_a1ac6f55fef555ee.jpg

İlk 10 basamak zaman damgasıdır ve arkasından a olanlar _belirli kimliklerdir. Belirli dosya adı kimlikleriyle eşleşen tüm dosyaları farklı bir klasöre taşımak istiyorum.

Bunu dosyaları ile dizinde denedim

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

Ancak ben belirten bir hata alıyorum:

bash 1559704165_a1ac6f55fef555ee.jpg: command not found

Denediğimde, mv ??????????_a1ac*.jpg argüman listesi çok uzun hata alıyorum. En az 15 farklı dosya adı desenim var. Onları nasıl hareket ettiririm.


1
Bash her şeyi söylüyor: bu dosya adını borunun 2. aşamasında ilk sırada olduğu gibi yürütmeye çalışıyor (2. aşama | ??????????_a1ac*.jpgborunuz:: bash bunu birkaç dosya adına genişletiyor, ilki 1559704165_a1ac6f55fef555ee.jpg, sonunda , bu 2. boru aşamasında, yürütmeye çalışıyorum: 1559704165_a1ac6f55fef555ee.jpg next_matching_filename 3rd_matching_filename ... nth_matching_filenameSanırım bunun yerine bu dosya adına filtre uygulamaya çalıştınız (bunun için aşağıdaki yanıtlara bakın)
Olivier Dulac

Yanıtlar:


15

Kullanmalısın:

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

Yani maxdepth 1geçerli dizinde alt dizin aramak istemediğiniz anlamına gelir.

type f yalnızca dosyaları bulmak anlamına gelir.

name '??????????_a1ac*.jpg' , aradığınız dosyayla eşleşen bir modeldir.

mv -t destination "{}" +eşleşen dosyaları hedefe taşımak anlamına gelir. Burada +önceki gibi yeni eşleşen dosyaları ekler:

mv -t dest a b c d

Burada abcd farklı dosyalardır.


Bu kişinin sorusunu kısaca cevapladığınız için teşekkür ederiz. Bir çözümü atmak yerine, nasıl / ne / neden olduğunu açıklayabilirsiniz. Bir kişiye, bir kereye mahsus olmak yerine, herkes için her zaman faydalı olabilir. Aynı soru son 40-50 yıl içinde sayısız kez sorulmuş ve cevaplanmıştır. Sorun ţu ki, asla iyi açýklanmamýţ. Bir adama balık tutmayı öğretin .. Bu arada: gnu.org/software/findutils/manual/html_node/find_html/… ve genellikle Wikipedia'nın resmi dokümanlardan daha yararlı olduğu gibi: en.wikipedia.org/wiki/Find_ ( Unix)
sesler

Güncellenmiş cevaba bakınız.
Prvt_Yadav

Bunun -tbir GNU uzantısı olduğunu ve diğer UNIX türevleri türlerinde bulunmayabileceğini unutmayın.
Kevin

Dediğinizde "Çift önler kelime bölme tırnak." Bahsettiğinizi varsayıyorum "{}", bu durumda {}kabuk tarafından genişletilmemiş ve alıntılanması gerekmediğini belirtmek istiyorum. Kabuk {}bulmak için geçer ve bulup {}onu yol adları ile değiştirir. Bulma exec, kabuk ayrıştırıcısını kullanmaz ve kendi başına sözcük ayırma yapmaz. Alıntı yapmak herhangi bir zarar vermez, sadece verilen gerekçenin biraz yanlış olması.
jw013

@ jw013 teşekkürler.
Prvt_Yadav

11

Emriniz,

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

Tüm dosyaların listesini tüm dosyalara yönlendirir!

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

hile yapacak.


1
çok teşekkürler ... çözümünüz de işe yaradı ... Nerede yanlış gittiğimi
Kayısı

8

Çok yakınsın. Sen kullanmalıdır -nameseçeneği find. Ve kalıbı alıntılamayı unutmayın.

Yani

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

Çok teşekkürler ... çözümünüz de çalıştı .... çözüme yakın olduğumu bildirmek için ek teşekkür .... benim gibi bir acemi için bir motivasyon
Kayısı

1
-print0bulmaya son bağımsız değişken olarak a (varsayılan: -print yerine) eklemeli ve xargs'a -0ilk seçenek olarak a eklemelisiniz (yani:) xargs -0 mv -t "/home/ubuntu/ntest". bu şekilde, her türlü garip dosya adı (içinde boşluklar, içinde "satırsonu" olan, vb.) ele alınabilir. find . -maxdepth 1 -type f -name '??????????_a1ac*.jpg' -print0 |xargs -0 mv -t "/home/ubuntu/ntest" (yine de sadece GNU benzeri buluntu ile çalışır)
Olivier Dulac

2

findÇözümler kadar "iyi" değil , başka bir geçerli çözüm de mvkomutları daha ayrıntılı hale getirmektir .

Bu mvişlem başına 4096 hamle yapar ve işlem başına daha az sayıda dosya taşınır .

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

Bu, find(ne sebeple olursa olsun) olmayanlar için akıllıca bir hack'tir .
orman

-1

Eğer ben aşağıdaki konularda yaptığını tahmin aynı ana sistemde, dosyaları taşımak istiyorsanız mv, rsyncdaha hızlı bir seçenek olabilir:

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

--inplaceve -Wsüreci hızlandıracak şekilde ayarlanmış.

Bu başka bir bağımsız değişken listesi çok uzun hata verirse,rsync

Listeyi find ile yapın, örneğin

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

ve ver rsync

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

Buradaki kaynak /path/to/files, çünkü rsyncverdiğiniz listeyi kaynağınıza göre ele alacaktır.


Asıl nokta: Dosyalar aynı dosya sisteminde değilse rsync, daha hızlıdırmv .


Bu büyük olasılıkla OP belirtilen aynı "argüman listesi çok uzun" hata vurmak
Grump

@Grump, bundan kaçınmak için OP bir dosyaya kopyalanacak dosyaların listesini yazabilir, yani find . -maxdepth 1 -type f -name '??????????_a1ac*.jpg' > /tmp/my_image_list.txtrsync'e aktarabilir --files-from=/tmp/my_image_list.txt. Önemli olan rsyncdaha hızlı. Dosyalar OP'nin belirtmediği aynı dosya sisteminde bulunmadıkça.
Robert Riedl

@RobertRiedl: Cevabınızı düzenlemeli ve bu bilgileri eklemelisiniz. Yorumlar geçici olmayabilir.
NickD

@ NickD, cevabımı güncelledim.
Robert Riedl
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.