Bir metin listesinden Linux (mv veya cp) belirli dosyalar?


34

50.000 pdf ve bir sunucudaki diğer dosyalar gibi pek çok dosyanın bulunduğu bir dizine sahibim. Belirli olanları başka bir dizine taşımam gerekiyor. Csv veya başka bir metin biçiminde taşınması gereken dosyaların bir listesini oluşturabilirim.

Yapmam gereken, bir bash betiği çalıştırmak ve metin dosyasında listelenen dosyaları başka bir dizine taşımak veya kopyalamak.

Bunu yapmanın kolay bir yolu var mı? Herhangi bir öneri veya kaynak çok takdir edilecektir.


Ayrıca, dosyalar dizine eklendiklerinde rasgele adlandırılır. Belirli dosyaları taşımak için kullanılabilecek hiçbir adlandırma kuralı ya da herhangi bir mantık yoktur.
Jestep

Yanıtlar:


26

rsync süreci (dosyaların bir listesini alabilir birkaç seçenek vardır --files-from, --include-fromvs.).

Örneğin, bu hile yapacak:

rsync -a /source/directory --files-from=/full/path/to/listfile /destination/directory

2
örnek:rsync -a /source/directory --files-from=/full/path/to/listfile /destination/directory
anneb

28

Bir işe yaramaz kullanımı önlemek için cat(ve kullanmazsanız rsync):

xargs -a file_list.txt mv -t /path/to/dest

Bu, dosyalar her satırda bir tane listeleniyorsa, yeni bir satır içermiyorsa geçerli bir dosya adını işleyecektir.


2
Bu yaklaşımın bir dezavantajı, listedeki dosyalar yol adlarını içeriyorsa (yani hepsi aynı dizinde değillerse), bunların kullanımı mvhepsini aynı hedef dizine daraltacaktır. rsyncKabul edilen cevap yaklaşım bu sınırlama muzdarip değildir.
Jason R

Ayrıca, bu komutu denedim ve xargs, tek bir alıntı ("eşsiz tek fiyat teklifi") içeren tüm dosyaları
kırar

Bu benim için işe yaradı, çünkü aslında dosyaları aynı hedef dizindeki farklı kaynak yollarından istedim.
PseudoNoise

15
for file in `cat listoffiles`; do mv "$file" /path/of/destination ; done

bash varsayalım, artı listoffilesher satıra bir dosya ekleyin. Rsync yoluna tek itirazım, OP'nin dosyaları kopyalamak değil, dosyaları taşımak için bir yöntem istediğidir. rsync'in kraliyet düğünüden daha fazla bayrağı var, bundan dolayı daha fazla modifiye edilebileceğinden eminim, ama bazen daha basit!


1
Bu çözümler beni en esnek olarak etkiliyor. Sadece göreceli dosya yolları seçeneğine ihtiyacım olduğu için cp veya mv yerine rsync ile kullandım.
Spamwich

4
Güzel, sadece boşluklarla ilgili problemlerim vardı, bu yüzden şu şekilde değiştirdim:while read -r file; do mv "$file" /path/of/destination ; done < listoffiles
user1182474

1
@ user1182474 Teşekkürler ve giriş yönlendirmesinin zarif bir kullanımı. Bir cevap ile memnuniyetini gösteren geleneksel yöntem, bu arada, artırmaktır!
MadHatter

1
@ user1182474 bunun için teşekkür ederim! birçok değişikliğin son adımı, OSX yedekleme yardımcı programlarımı Android'ime taşımak için biraz kör yapmak zorundaydı!
Charlie Gorichanaz

4

Bu, sahip olduğunuz metin dosyasının biçimine bağlıdır. Örneğin, her dosyanın yeni bir satırda bulunacağı şekilde yazılmış dosyaların listesi varsa. Gibi xargs kullanabilirsiniz:

$ cat your_text_file | xargs cp -t /path/to/destination

Ayrıca, seçeneği findile komut kullanabilirsiniz -exec. Dosyaları kopyalamak / taşımak için


3
rsync --files-from=file_list.txt /path/to/source/ /path/to/dest/

Rsync, cpya da mvkomutları üzerinde ek bir faydayı sağladı, çünkü yoksa, otomatik olarak klasörler oluşturacak.


/path/to/sourceYolları dosya listesinden alırken neden gerekli?
bzero

@bzero belki dosya listesi göreceli yollar içerebilir?
DreadfulWeather

2

Bence rsync cevabı daha iyi bir cevap, fakat sadece başka bir seçenek için:

tar -cf - -T FILE_OF_FILENAMES_TO_MOVE.txt |(cd /path/to/new/dir && tar -xvf -)

Bu, ubuntu temel görüntüsünde katran mevcut olduğundan, ancak rsync'de olmadığı için bir Docker dosyası için iyidir.
kristianp

1

Tüm dizini taşımak yerine yanlışlıkla bir dizinin tüm içeriğini bir hedef dizine kopyaladım. Bu, dizine eklenen orijin dizini yerine darmadağın bir hedef diziniyle sonuçlandı.

Bunu düzeltmek için aşağıdakileri yaptım:

ls -rt /path/to/cluttered/destination/directory/ > /opt/dircheck/filestomove Yukarıdaki komut, hedef dizinin tüm içeriğinin bir listesi olacak filestomove dosyasını yaratır, zamana göre tersine sıralanır, en eskiden en yeniye anlamına gelir.

Daha sonra, malzemeleri içine taşımak için şimdi dağınık hedef dizinin bir alt dizinini yarattım.

mkdir /path/to/cluttered/destination/directory/newsubdirectory

Sonra dizinde listeleme, ekrana listeleme ve daha fazla ayrıntı gösterme dışında tekrarladım.

ls -lrht /path/to/cluttered/destination/directory/ Bu satır, artan tarihe göre sıralanan dizini listeler (zamana göre geriye doğru sırala) ve şimdi dağınık hedef dizindeki her bir dosyanın tarih / saat damgası dahil olmak üzere daha fazla bilgi gösterir. Hangi dizinleri ve dosyaları bulundukları yerde saklamak istediğimi göstermek için en baştan başlayarak buna atıfta bulunuyorum. Tüm yeni dosyaların başlatılmaması gereken dosyaların tarih / saat damgasında bir boşluk olacaktır.

Sonra, yukarıdaki ilk adımda yaratılan filestomove dosyasını düzenledim (tarihe göre sıralandı) ve daha önce orjinal dizinden kalmak istediğim listeden birkaçını sildim.

vim /opt/dircheck/filestomove Yukarıdan silin, taşımak istemediğiniz tüm dosyaları silin.

Sonra listemdeki dosyaları yaptığım yeni dizine taşımak için bu yazıda daha önce listelenen komutu kullandım.

sudo xargs -a /opt/dircheck/filestomove mv -t /path/to/cluttered/destination/directory/newsubdirectory

Bu, tüm dosyaları bölünmüş bir saniye içinde taşıdı. (Not: Başlangıçta sudoya ihtiyacınız olmayabilir, bu dosya izinleri konusudur).

Şimdi, orijinal hedef dizinim güzel ve temiz ve tüm dosyaları ve dizeleri karışık bir şekilde içeren yeni bir dizin içeriyor.


1

Eğer (ve sadece ise), dosya isimlerinde kötü karakterler bulunmaz (boşlukları, yeni satırları, xarg'ların nesneleri bireysel argümanlara nasıl ayıracağını karıştırırlar) ve yeni satırlarla ayrılmış bir dosya listesi oluşturursunuz (bir dosya satır başına), gibi bir şey yapabilirdi.

cat filenames.txt | xargs mv -t /path/to/move/files/to

(Genel olarak, bakınız adam xargs , bu harika)

Özel mv'niz -t seçeneğine sahip değilse, bazı hileler de yapabilirsiniz.

( cat filenames.txt; echo; echo /path/to/move/files/to ) | xargs mv

Not - bunlardan hiçbiri, içinde yeni satır bulunan dosya adları varsa, beklendiği gibi çalışmayacaktır.


Ancak; Ignacio'nun cevabını görün, rsync bu şeyler için bir nevi yaratılmış.
Kjetil Joergensen

cp, mvve benzerlerinin bsd-t üzerinde seçeneği yoktur ve subshell ile ikinci örnek benim için işe yaramadı ( /path/to/moveson dosya adı olarak eklenir)

1
@ w17t - filenames.txt gibi sesler yeni bir satırla bitmiyor, ya filenames.txt'nin sonuna yeni satır ekliyor ya da şöyle bir şey yapıyor(cat filenames.txt; echo; echo /path/to/move/files/to) | xargs mv
Kjetil Joergensen

0

Gibi bir şey deneyin:

cat list.txt | while read line; do mv "$line" /images; done

olabilirdi while read line; do mv $line /images; done < list.txt tek komutla olarak
ignivs

0

Dizin yapısını koruyarak, tüm PNG dosyalarını belirli bir yoldan (ve tüm alt dizinleri) yeni bir konuma kopyalamam gereken yerler benim için işe yaradı.

rsync -av --prune-empty-dirs --include='*/' --include='*.png' --exclude='*' source/ destination/

RSYNC ilk önce dizin yapısının aynasını yarattığından, ardından dosyaları senkronize ettiğinden, fazla boş klasörlerle karşılaşabilirsiniz. Bu boş dizinleri kaldırmak için --prune-empty-dirs bayrağını kullandım.

Hiçbir üyeliğim yok, ancak bu çözüme ilham veren kaynağa kredi vermenin doğru olacağını düşündüm: http://techblog.zabuchy.net/2011/transfer-only-selected-file-types-with-rsync/

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.