Dosyaların listesini kopyala


35

Dosyadaki boşluklarla ayrılmış dosyaların bir listesi var list.txt. Onları yeni bir klasöre kopyalamak istiyorum.

Yapmaya çalıştım:

cp `cat list.txt` new_folder

Ama çalışmadı.

Bunu nasıl yapardın ?

Güncelleştirme:

Tüm ilginç cevaplarınız için teşekkür ederim. Ben o kadar istemedim :)

Çözümü ikinci kez yukarıda denedikten sonra cp, klasör new_folderhenüz bulunmadığından kullanım yardımı yazdırılmış görünüyor ! Üzgünüm, aptalca bir hata gibi görünüyor ... Önceden klasörü oluşturduğumda işe yarıyor.

Ancak tüm cevaplarınız ve çözümleriniz hakkında çok şey öğrendim, yazdığınız zaman için teşekkür ederim.


Bir şeyi açıklığa kavuşturmama izin verin: listedeki tüm dosya adları bir satırda, yalnızca boşlukla ayrılmış mı? Yoksa isimler ayrı bir satırda mı?
Telemachus

Hepsi bir kireç içinde, bir boşlukla ayrılmış. Doug'ın çözümü işe yaradı :) Cevap için teşekkür ederim.
Klaus

Bu komik ... Çözümümü, her ismin ayrı bir satırda olduğu bir çizgi ile test ettim.
Doug Harris,

“İşe yaramadı” çok anlamlı değil. Tam olarak nasıl işe yaramadı. Benim için iyi çalışıyor.
sonraki duyuruya kadar duraklatıldı.

Üzgünüz: cp kullanım yardımı gösterdi. Yukarıdaki güncellememe bakın.
Klaus

Yanıtlar:


34

Xargs kullanmayı deneyin:

cat list.txt | xargs -J % cp % new_folder

Güncelleştirme:

Bunu GNU / Linux versiyonlarından farklı bir versiyona sahip olan OS X'te yaptım. xargsDan geldiği GNU findutils yok -Jama sahiptir -I(Dennis Williamson yorumunda belirttiği gibi) benzer olan. Xargs'ın OS X sürümü her ikisine de sahip -Ive -Jbiraz farklı davranışları var - bu orijinal soru için işe yarayacak.

$ cat list.txt
one
two.txt
three.rtf

$ cat list.txt | xargs -J % echo cp % new_folder
cp one two.txt three.rtf new_folder

$ cat list.txt | xargs -I % echo cp % new_folder
cp one new_folder
cp two.txt new_folder
cp three.rtf new_folder

3
Benim de aynı şeyi xargsyapmamış -Jgibi görünmüyor -I. Hangi sürüm xargsve hangi işletim sistemi / dağıtımınız var?
sonraki duyuruya kadar duraklatıldı.

Bunu Mac OS X 10.6'da (aka kar leoparı) test ettim, bu yüzden Xargs'ın işletim sistemi ile birlikte gelen sürümü budur. Çalışan xargs --versionbir kullanım hatası mesajı veriyor. Muhtemelen xargs’ın BSD versiyonu. Kullanımı -Ive -Jincelikle farklıdır. Cevabımı güzelce biçimlendirilmiş örneklerle güncelleyeceğim.
Doug Harris

Evet, Mac OSX 10.6 ile çalışıyorum. Hakkında Precisions için teşekkür ederiz -Jve -I:)
Klaus

Bu, çalıştırmadan önce komutlarınızı kontrol etmek için yankı kullanmak için iyi bir ipucu.
Liam

1
Aynı yukarıdaki komutu yalnızca gerekli değişikliklerle birlikte kullanarak dosyaları, içinde bulundukları dizinleri ve alt dizinleri, eğik çizgi ile ayırarak birlikte nasıl kopyalarım?
Vicky Dev

54

Buna hiç gerek yok cat:

xargs -a list.txt cp -t new_folder

Veya uzun seçenekleri kullanarak:

xargs --arg-file=list.txt cp --target-directory=new_folder

İşte bazı kabuk sürümleri. Bazı değişkenlerin işaretlenmemiş olduğunu veya fordöngüler özel olarak kullanıldığını unutmayın; çünkü OP, dosya adlarının boşlukla ayrılmış olduğunu belirtti. Bu tekniklerden bazıları, dosya adlarında beyaz boşluk bulunan satır başına dosya girişi için çalışmaz.

Bash:

for file in $(<list.txt); do cp "$file" new_folder; done

veya

cp $(<list.txt) new_folder

sh (veya Bash):

# still no cat!
while read -r line; do for file in $line; do cp "$file" new_folder; done; done < list.txt

veya

# none here either
while read -r line; do cp $line new_folder; done < list.txt

veya

# meow
for file in $(cat list.txt); do cp "$file" new_folder; done

veya

# meow
cp $(cat list.txt) new_folder

noob soru: neden -tihtiyaç duyulmaktadır xargs -a list.txt cp -t new_folder?
Yibo Yang,

1
@ YiboYang: Bu -tbir seçenek cp. Tüm kaynak argümanlarını belirtilen hedef dizine kopyalar. Burada, hedefin xargskomut tarafından eklenen kaynaktan önce belirlenmesini sağlar .
sonraki duyuruya kadar duraklatıldı.

Bu yararlıdır, ancak list.txt karışık dosyalar ve klasörler yolu içeriyorsa ne olur? Bu durumda komut düzgün çalışmıyor. "Omitting dizini ..." bildirir ve cp komutuna -R belirtilirse, listedeki ilk dosyayla karşılaşılır karşılaşmaz "dizin değildir" hatası bildirilir.
Bemipefe

7

Daha önce bu konuda utanç verici bir yanıt almıştım ancak Denis'in cevabı en temel şeyi özlediğimi hatırlattı. Böylece orijinal cevabımı sildim. Fakat hiç kimse bu çok temel şeyi söylemediğinden , onu buraya koymaya değeceğini düşünüyorum.

Asıl soru "Boşluktan ayrılmış dosya adlarının bir listesini içeren bir metin dosyam var. Bunları bir hedef dizine nasıl kopyalarım?" İlk başta bu biraz karmaşık veya karmaşık görünebilir, çünkü dosyadaki öğeleri bir şekilde belirli bir şekilde çıkarmanız gerektiğini düşünüyorsunuz. Bununla birlikte, kabuk bir komut satırını işlediğinde, yaptığı ilk şey argüman listesini belirteçlere ayırır ve (işte hiç kimse tam olarak söylemediği bit) ayrı belirteçleri boşluklar . (Newlines ayrıca ayrı simgeleri belirttiğinden, bu nedenle Doug Harris'in yeni satırlı ayrılmış bir listeyle yaptığı test aynı sonucu vermiştir.) Kabuk, boşluktan ayrılmış bir listeyi bekler ve zaten işleyebilir.

Dolayısıyla burada yapmanız gereken tek şey boşlukla ayrılmış listeyi (zaten sahip olduğunuz) emrinizde doğru yere koymak. Komutunuz bu konuda bir varyasyon:

cp file1 file2 file3...file# target

Tek kırışıklık, metin dosyanızdan 1 ile # arasındaki dosyaların listesini almak istemenizdir.

Dennis'in yorumunda işaret ettiği gibi, orijinal girişiminiz ( cpcat list.txt new_folder) çoktan işe yaramalıydı . Niye ya? Çünkü iç komut cat list.txtönce kabuk tarafından işlenir ve genişler file1 file2 file3...file#, bu tam olarak kabuğun komutun bu bölümünde beklediği ve istediği şeydir. Eğer işe yaramadıysa (1) ya da bir yazım hatası vardı ya da (2) dosya adlarınız bir şekilde tuhaftı (boşlukları ya da sıra dışı karakterleri vardı).

Tüm Dennis'in cevaplarının çalışmasının nedeni, cpüzerinde çalışılacak dosyalar listesini sağlamaları ve bu listeyi tüm komutun içinde yer almasıdır. Yine komutun kendisi şu şekildedir:

cp list-of-files target_directory

Tüm bunların bu sürümde nasıl bir araya geldiğini görmek kolaydır:

cp $(<list.txt) new_folder

$()kabuğun parantez içindeki komutu çalıştırmasına ve daha sonra çıktısını daha büyük satırdaki yerine koymasına neden olur. Sonra kabuk çizgiyi bir bütün olarak çalıştırır. Bu arada, $()zaten backtick'lerle yaptığın şeyin daha modern bir versiyonudur (`). Sonraki: <bir dosya yönlendirme operatörü. Kabuğa içeriğini list.txtstandart girdilere dökmesini söyler . Yana $()biraz ilk işlemden geçiyor burada aşamada gerçekleşir:

  1. cp $(<list.txt) new_folder # split line into three tokens: cp, $(<list.txt), new_folder
  2. cp file1 file2 file3...file# new_folder # substitute result of $(<list.txt) into the larger command

Açıkçası 2. adım basitçe istediğiniz normal cpkomuttur.

Bu (belki de çok ölü) atı çokça attığımın farkındayım, ama bence yapmaya değer. Kabuğun bir komutu tam olarak nasıl işlediğini anlamak , onu daha iyi yazmanıza ve çok basitleştirmenize yardımcı olabilir. Ayrıca, sorunların nerede gizlenebileceğini gösterir. Bu durumda, örneğin, size ilk sorum komik dosya isimleri veya olası bir yazım hatası ile ilgili olmalıydı. Akrobasi gerekmez.


@Klaus Çok rica ederim. Dürüst olmak gerekirse, Dennis'in cevabını okuduktan ve problemin anahtar bölümünü tamamen özlediğimi farkettikten sonra çoğunlukla kendime kızdım. Beğendiğiniz çözüm de oradan.
Telemachus

Bu çok eski bir cevap, ancak klasör yapısını yeniden oluşturmanız gerekirse, --parentsbayrağa ihtiyacınız var . -vNelerin kopyalandığını kayıt etmek için detaylı bir şekilde yapabilirsiniz . İzinleri saklamak istiyorsanız, -aveya -pişaretine ihtiyacınız vardır . Yani cp --parents -av $(<list.txt) new_folder,. Bunların hepsi, dosya listenizin gerçekten tüm dosyalar olduğunu varsayar, aksi takdirde -ryinelenmek için de bayrağa ihtiyacınız olabilir .
dhaupin

@dhaupin Aslında, OP onun macOS'ta olduğunu belirtir. Yani buna değer, --parentsbayrak orada yok. Bunların (BSD türevi) sürümleri cpGNU tarzı uzun seçenekler değil yalnızca kısa seçenekler sunar. Bir BSD stili cpiçin özyinelemeli kopya için bayrak -Rküçük harf değil , büyük harftir .
Telemachus
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.