Gnu cp komutunu kullanarak bir dosyayı birden çok dizine kopyalama


210

Cp komutunu kullanarak tek bir dosyayı birden çok dizine kopyalamak mümkün mü?

Ben işe yaramadı, aşağıdakileri denedim:

cp file1 /foo/ /bar/
cp file1 {/foo/,/bar}

Bir for döngüsü kullanmanın veya bulmanın mümkün olduğunu biliyorum. Ancak gnu cp komutunu kullanmak mümkün müdür?

Yanıtlar:


106

Hayır, cpbirden fazla kaynağı kopyalayabilir , ancak yalnızca tek bir hedefe kopyalar. Yapmak cpistediğiniz şey için hedef başına bir kez olmak üzere birden çok kez çağırmanız gerekir ; Dediğiniz gibi, bir döngü veya başka bir araç kullanarak.


Cevap için teşekkürler! Şimdi biraz daha düşünün, ekstra bayraklar olmadan (ki mevcut değil) cp kaynak ve DEST dir nedir bilmeyecektir.
Tom Feiner

10
Bu doğru cevap değil. Lütfen Robert Gamble'ın cevabına bakınız.
PlagueHammer

23
@Nocturne: Söylediklerimin hangi kısmı yanlış? Robert, önerdiğim gibi cp'yi birkaç kez çağırmak için başka bir araç kullanma örneği veriyor. Bunu yapmak için diğer araçların veya yapıların kullanılmasını içeren birçok olası çözüm vardır, ancak OP bunun mümkün olduğunun farkında olduğunu gösterdi.
moonshadow

2
Üzgünüm, cp (ve scp) 'nin bu özelliği desteklemesi harika olurdu. Yine de bölünmeyi yapmak için tee'yi kullanabiliriz. superuser.com/questions/32630/…
Simon

4
@moonshadow: Elbette cevabınız doğru. Bence PlagueHammer, bu bağlamda diğer cevabın daha faydalı olduğunu söylemek istiyor. Belki cevabınıza böyle bir şey de dahil edebilirsiniz?
Barışçıl

585

Sen ile bunu yapamaz cpyalnız ama birleştirebilirsiniz cpile xargs:

echo dir1 dir2 dir3 | xargs -n 1 cp file1

Kopyalar file1için dir1, dir2ve dir3. xargsbunu cpyapmak için 3 kez arayacak , ayrıntılar için kılavuz sayfasına xargsbakınız.



24
@Simon nasıl yani? “Bunu cptek başınıza yapamazsınız ” Sadece cevabın başka bir yol önererek yardımcı olmaya çalışması, sorunun cevaplanmadığı anlamına gelmez.
Nicole

3
@NickC Asker şöyle dedi: "Bir for döngüsü veya bulmanın mümkün olduğunu biliyorum. Ama gnu cp komutunu kullanmak mümkün mü?" İyi cevap kabul edilen cevaptır.
Simon

25
Cevapların teknik olarak soruya cevap verip vermediklerine göre kabul edilmesini şart koşmak, yeterince bilgiçlik yapmaz ve gerçekten yararlı olmaz.
Tavla

4
Çok yararlı! Benim gibi diğer yeni başlayanlar için: regex'i cp ile kullanamazsınız, ancak bu komutun ilk bölümünde (örneğin echo dir[1-3] | xargs -n 1 cp filename) kullanabilirsiniz.
Jason

77

Joker karakterler Roberts koduyla da çalışır

echo ./fs*/* | xargs -n 1 cp test 

ve tüm yorum ... Örneğin, masaüstümde bulunan kök sahip bir dosyayı (aslında bir symlink) tüm kullanıcıların masaüstüne taşımak için önce sudo su (aksi halde çalışmadı) sonra kullandım: echo / home / * / Masaüstü / | xargs -n 1 cp -av / home / kullanıcı adı / Masaüstü / dosya.
David G

19

Görebildiğim kadarıyla aşağıdakileri kullanabilirsiniz:

ls | xargs -n 1 cp -i file.dat

-iSeçeneği cpkomut vasıtası sizinle geçerli dizinde bir dosyanın üzerine isteyip istenecek o file.dat. Tamamen otomatik bir çözüm olmamasına rağmen benim için çalıştı.


1
Korumayı eklemeniz iyi olsa da, -ibu sizi her dosyanın üzerine yazmak konusunda uyarmaz mı? dizinlere kopyalamak yerine?
Hedgehog

1
@ Hedgehog Eh, bu komut dizinde bir dosya olduğunda ve biri dizinin alt dizinlerine kopyalamak istediğinde yararlı olduğunu düşünüyorum. Bu durumda bir dosyanın üzerine sadece bir kez yazılabilir. Sorunuz için teşekkürler!
Evgeny

2
Benim için bir dizi cp: overwritesoru yazdırdı , ancak bunlardan hiçbirine cevap vermek zorunda kalmadım ve dosyaların üzerine yazmadı.
Evgeni Sergeev

Ayrıca bir dizi soru
yazdı +

19

Ben kullanmak catve teeben gördüğüm yanıtlara dayalı /superuser/32630/parallel-file-copy-from-single-source-to-multiple-targets yerine cp.

Örneğin:

cat inputfile | tee outfile1 outfile2 > /dev/null

1
Az önce koştuğum bir cursory testi, hedefleriniz farklı fiziksel sürücüler ise (dijital film için kaynak video gibi bir dosya tabanının iki fiziksel kopyasını tutarsa) bunun en iyi performans sergilediğini gösterir.
daha meraklı

1
Eğer bash 3.0 veya üzerini kullanıyorsanız, aralıkları aşağıdaki gibi kullanabilirsiniz:cat <inputfile> | tee /path-to-files/outfile{1..4} > /dev/null
Samuel

tee < inputfile outfile1 outfile2 > /dev/nullTaywee'nin cevabında gösterildiği gibi faydalı bir modeldir. '<' İle io-yeniden yönlendirme kullanımına dikkat edin, böylece kediden borulamaya gerek yoktur.
Alex Telon

10

Bu cevapların hepsi açık olandan daha karmaşık görünüyor:

for i in /foo /bar; do cp "$file1" "$i"; done

zarif ve çalışan, geçerli dizindeki tüm dizinler için yapmak, bir kullanabilirsinizfor d in */ ; do cp $file "$i" done
FantomX1

9

ls -db di*/subdir | xargs -n 1 cp File

-bdizin adında bir boşluk olması durumunda, aksi takdirde xargs tarafından farklı bir öğe olarak kırılacak, echo sürümü ile bu sorunu vardı


6

CP'yi kendi başına kullanmamak, ama ...

Bu benim için (yavaş) bir SD karttan çok sayıda Gopro çekimini üç (yavaş) USB sürücüye kopyalama bağlamında geldi. Verileri sadece bir kez okumak istedim, çünkü sonsuza dek sürdü. Ve özyinelemesini istedim.

$ tar cf - src | tee >( cd dest1 ; tar xf - ) >( cd dest2 ; tar xf - ) | ( cd dest3 ; tar xf - )

(Daha fazla çıktı istiyorsanız bu> () bölümlerden daha fazlasını ekleyebilirsiniz.)

Bunu kıyaslamadım, ama kesinlikle cp-in-a-loop'dan (veya bir grup paralel cp çağrısından) çok daha hızlı.


5

İle kopyalama kullanmak için xargsMac OS, benim için çalıştı tek çözüm üzerinde joker kullanarak dizinlere ile dizin adıdır içinde boşluklar:

find ./fs*/* -type d -print0 | xargs -0 -n 1 cp test 

Nerede testkopyalamak dosyasıdır
Ve ./fs*/*kopya dizinleri için

Sorun, xargs'ın boşlukları yeni bir argüman olarak görmesi, sınırlayıcı karakterini değiştirme çözümleri -dveya -EMac OS'de ne yazık ki düzgün çalışmıyor olması.


4

Çatallı komut olmadan yapmak istiyorsanız:

tee <inputfile file2 file3 file4 ... >/dev/null


2

Temelde xargs cevabına eşdeğerdir, ancak paralel yürütme istiyorsanız:

parallel -q cp file1 ::: /foo/ /bar/

Örneğin, file1 dosyasını geçerli klasörün tüm alt dizinlerine kopyalamak için (özyineleme dahil):

parallel -q cp file1 ::: `find -mindepth 1 -type d`

Not: Bu, muhtemelen çok özel kullanım durumları için, örneğin her hedef dizin ayrı bir diskse, fark edilebilir herhangi bir hız kazanımı sağlar.

Ayrıca xargs için '-P' argümanına işlevsel olarak benzer.


0

Hayır yapamazsın.

Birden çok kez bu işlevselliği kullanabileceğimi buldum, bu yüzden bunu benim için yapmak için kendi aracımı yaptım.

http://github.com/ddavison/branch

gayet basit -
branch myfile dir1 dir2 dir3


Sık sık böyle bir senaryomu yazacağım senaryolar var, ama bugünlerde hepsini senkronize tutmak büyük bir güçlük gibi görünen birçok makine kullanma eğilimindeyim. Bir bulut web dizinini /eörneğin her makineye yalnızca bir kez bağlamanın bir yolu olsaydı , o zaman kendi elektrikli aletlerimi yazabilir ve sonsuza kadar tutabilirdim.
Evgeni Sergeev

0
ls -d */ | xargs -iA cp file.txt A

1
Biraz açıklama yapmaya ne dersiniz?
dakika

Bu gerçekten işe yarıyor, ama bir açıklama harika olurdu
Declex

0

fileName.txtMevcut çalışma dizinindeki tüm alt dizinlere kopyalamak istediğinizi varsayalım .

  1. Tüm alt dizin adlarını alın lsve bunları geçici bir dosyaya kaydedin,allFolders.txt

    ls > allFolders.txt
  2. Listeyi yazdırın ve komuta iletin xargs.

    cat allFolders.txt | xargs -n 1 cp fileName.txt

0

Başka bir yol kedi ve tişörtü aşağıdaki gibi kullanmaktır:

cat <source file> | tee <destination file 1> | tee <destination file 2> [...] > <last destination file>

İşin birkaç işlem arasında (hedef başına bir tane) bölüneceği ve sabit diskin tabağın farklı bölümleri üzerinde bir kerede birkaç dosya yazacağı için bu olsa da oldukça verimsiz olacağını düşünüyorum. Ancak, birkaç farklı sürücüye bir dosya yazmak istiyorsanız, bu yöntem muhtemelen oldukça verimlidir (tüm kopyalar aynı anda gerçekleşebileceğinden).


0

Bir bash betiği kullanma

DESTINATIONPATH[0]="xxx/yyy"
DESTINATIONPATH[1]="aaa/bbb"
                ..
DESTINATIONPATH[5]="MainLine/USER"
NumberOfDestinations=6

for (( i=0; i<NumberOfDestinations; i++))
    do
        cp  SourcePath/fileName.ext ${DESTINATIONPATH[$i]}

    done
exit

Bunu bir aşağılık oy verdim. Soru özellikle döngüsel olmayan bir çözüm istedi.
Alex Telon

-1

birden çok klasörü birden çok klasöre kopyalamak istiyorsanız, böyle bir şey yapabilirsiniz:

echo dir1 dir2 dir3 | xargs -n 1 cp -r / yol / yolunuz / {altdir1, altdir2, altdir3}


-1

Tüm hedef dizinleriniz bir yol ifadesiyle eşleşiyorsa (tümü alt dizinleri gibi), path/toyalnızca findbununla birlikte kullanın cp:

find ./path/to/* -type d -exec cp [file name] {} \;

Bu kadar.


Bunu bir aşağı not verdim. Soru özellikle bulunmayan bir çözüm istedi.
Alex Telon

@AlexTelon kadar kapsamlı olduğunuz için teşekkürler. Sanırım o kısmı kaçırdım. Umarım siz de tutarlı olursunuz ve her bir cevaba findiplik kullanarak aşağı oy verdiniz .
Mig82

-2

Dosyayı hangi klasörlere kopyalayacağınız konusunda spesifik olmanız gerekiyorsa, bulmayı bir veya daha fazla açılır pencere ile birleştirebilirsiniz. Örneğin, herhangi bir alt klasördeki favicon.ico oluşumunu değiştirmek için şunları kullanabilirsiniz:

find . | grep favicon\.ico | xargs -n 1 cp -f /root/favicon.ico

-3

Bu, derhal alt dizinlere kopyalanır, daha derine inmek istiyorsanız, -maxdepthparametreyi ayarlayın .

find . -mindepth 1 -maxdepth 1 -type d| xargs -n 1 cp -i index.html

Tüm dizinlere kopyalamak istemiyorsanız umarım ilginizi çekmeyen dizinlere filtre uygulayabilirsiniz. Örnek ile başlayan tüm klasörlere kopyalama a

find . -mindepth 1 -maxdepth 1 -type d| grep \/a |xargs -n 1 cp -i index.html

İsteğe bağlı / ayrık bir dizin grubuna kopyalama yapıyorsanız, Robert Gamble'ın önerisine ihtiyacınız olacaktır.


-3

Bir dosyayı birden çok dizin içine kopyalamak istiyorum: cp file1 /foo/; cp file1 /bar/; cp file1 /foo2/; cp file1 /bar2/ Ve bir dizini diğer dizinlere kopyalama: cp -r dir1/ /foo/; cp -r dir1/ /bar/; cp -r dir1/ /foo2/; cp -r dir1/ /bar2/

Bunun birkaç komut vermek gibi olduğunu biliyorum, ama 1 satır yazmak ve bir süre uzaklaşmak istediğimde benim için iyi çalışıyor.


7
6 yaşındaki bir soruyu 15 cevap ile cevaplıyorsunuz. Cevabınız oldukça yeni olmalı. Bence - öyle değil.
Craig S. Anderson

-4

Örneğin, hedef klasörlerinizin üst dizinindeyseniz şunları yapabilirsiniz:

i için $ (ls); cp kaynak dosyası $ i; tamam


Soru, for döngüsü ile mümkün olduğunu söylüyor, bu yüzden bu gerçekten hiçbir şey eklemiyor.
LJNielsenDk

Downvoted. Aslals değişkenlerin çıktısını ayrıştırmaya çalışmayın ve her zaman değişkenleri alıntılayın. for i in ./*; do cp sourcefile "$i"; done
sleblanc
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.