Jak skopiować plik do wielu katalogów za pomocą polecenia gnu cp


210

Czy można skopiować pojedynczy plik do wielu katalogów za pomocą polecenia cp?

Próbowałem następujących, które nie działały:

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

Wiem, że jest to możliwe przy użyciu pętli for lub find. Ale czy jest to możliwe przy użyciu polecenia gnu cp?

Odpowiedzi:


106

Nie, cpmożna skopiować wiele źródeł, ale skopiuje tylko do jednego miejsca docelowego. Musisz zorganizować cpwielokrotne wywoływanie - raz na miejsce docelowe - dla tego, co chcesz zrobić; używając, jak mówisz, pętli lub innego narzędzia.


Dziękuję za odpowiedź! Teraz, gdy myślę o tym trochę więcej, bez dodatkowych flag (które nie istnieją) cp nie będzie wiedział, co jest źródłem, a co DEST reż.
Tom Feiner

10
To nie jest poprawna odpowiedź. Zobacz odpowiedź Roberta Gamble.
PlagueHammer

23
@Nocturne: która część tego, co powiedziałem, jest nieprawidłowa? Robert podaje przykład użycia innego narzędzia do wielokrotnego wywoływania CP, jak sugeruję. Istnieje wiele możliwych rozwiązań, które polegają na użyciu innych narzędzi lub konstrukcji do tego celu, ale PO wskazał, że już wiedział, że jest to możliwe.
księżyc księżyca

2
Niestety byłoby wspaniale, gdyby cp (i scp) wspierały tę funkcję. Jednak możemy użyć tee do podziału. superuser.com/questions/32630/…
Simon

4
@moonshadow: Oczywiście twoja odpowiedź jest poprawna. Myślę, że PlagueHammer chce powiedzieć, że w tym kontekście druga odpowiedź jest bardziej przydatna. Być może w odpowiedzi umieścisz coś takiego?
Spokojnie,

585

Nie możesz tego zrobić cpsam, ale możesz połączyć cpz xargs:

echo dir1 dir2 dir3 | xargs -n 1 cp file1

Skopiuje file1się dir1, dir2oraz dir3. xargszadzwoni cp3 razy, aby to zrobić, zobacz stronę podręcznika, aby xargsuzyskać szczegółowe informacje.


3
Więcej informacji na temat xargs: cyberciti.biz/faq/…
Chris Bier

24
@ Simon jak to zrobić? „Nie możesz tego zrobić cpsam”. Tylko dlatego, że odpowiedź była pomocna, sugerując inny sposób, nie oznacza, że ​​na pytanie nie udzielono odpowiedzi.
Nicole,

3
@NickC Pytający sprecyzował: „Wiem, że jest to możliwe przy użyciu pętli for lub find. Ale czy jest to możliwe przy użyciu polecenia gnu cp?” Dobra odpowiedź to jedna zaakceptowana.
Simon

25
Zastrzeganie, że odpowiedzi będą akceptowane na podstawie tego, czy technicznie odpowiedzą na pytanie, byłoby zbyt pedantyczne i niezbyt przydatne.
Tryktrak

4
Bardzo pomocne! Dla innych początkujących, takich jak ja: nie możesz używać wyrażenia regularnego z cp, ale możesz w pierwszej części tego polecenia (np echo dir[1-3] | xargs -n 1 cp filename.).
Jason

77

Symbole wieloznaczne działają również z kodem Robertsa

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

i cały komentarz ... Na przykład, aby przenieść plik będący własnością root (właściwie dowiązanie symboliczne), który był na moim pulpicie na pulpit wszystkich użytkowników, najpierw musiałem sudo su (nie działał inaczej), a następnie użyłem: echo / home / * / Desktop / | xargs -n 1 cp -av / home / myusername / Desktop / file.
David G,

19

O ile widzę, możesz użyć następujących czynności:

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

-iOpcja cppomocą poleceń, które będą się pytanie, czy zapisać plik w bieżącym katalogu z file.dat. Chociaż nie jest to w pełni zautomatyzowane rozwiązanie, udało mi się.


1
Chociaż dobrze jest dodać -istrażnika, czy nie zachęci cię to do zapisania każdego pliku? zamiast kopiowania do katalogów?
Jeż

1
@ Jeż Cóż, myślę, że to polecenie jest przydatne, gdy w katalogu znajduje się plik i chce się go skopiować do podkatalogów katalogu. W takim przypadku plik można zastąpić tylko raz. Dziękuję za twoje pytanie!
Evgeny

2
Dla mnie wydrukował serię cp: overwritepytań, ale nie musiałem odpowiadać na żadne z nich i nie zastąpił plików.
Evgeni Sergeev

Wydrukowano również serię pytań + skopiowano do pliku o nazwie dir ze znakiem „:” na końcu, brak działającego rozwiązania, rozwiązanie Paula działa idealnie
jgpATs2w

19

Chciałbym użyć cati teena podstawie odpowiedzi, które widziałem na /superuser/32630/parallel-file-copy-from-single-source-to-multiple-targets zamiastcp .

Na przykład:

cat inputfile | tee outfile1 outfile2 > /dev/null

1
Pobieżny test, który właśnie uruchomiłem, pokazuje, że jest to najlepszy wynik, jeśli miejscem docelowym są różne dyski fizyczne (przechowujące dwie fizyczne kopie bazy plików, takie jak źródłowe wideo do filmu cyfrowego).
curiouser

1
Jeśli korzystasz z wersji bash 3.0 lub nowszej, możesz używać zakresów w następujący sposób:cat <inputfile> | tee /path-to-files/outfile{1..4} > /dev/null
Samuel

tee < inputfile outfile1 outfile2 > /dev/nulljest również użytecznym wzorem, jak pokazuje odpowiedź Taywee. Zwróć uwagę na użycie przekierowania io z „<”, aby rurociągi od kota nie były potrzebne.
Alex Telon

10

Wszystkie te odpowiedzi wydają się bardziej skomplikowane niż oczywiste:

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

elegancki i działający, aby zrobić to dla wszystkich katalogów w bieżącym katalogu, można użyćfor d in */ ; do cp $file "$i" done
FantomX1

9

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

-bw przypadku, gdy w nazwie katalogu jest spacja, w przeciwnym razie zostanie ona podzielona przez xargs jako inny element, miał ten problem z wersją echa


6

Nie używam cp per se, ale ...

To przyszło mi do głowy w kontekście kopiowania wielu nagrań Gopro z (wolnej) karty SD na trzy (wolne) dyski USB. Chciałem odczytać dane tylko raz, ponieważ zajęło to wieczność. I chciałem, żeby to było rekurencyjne.

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

(I możesz dodać więcej z tych sekcji> (), jeśli chcesz uzyskać więcej wyników).

Nie testowałem tego, ale jest zdecydowanie dużo szybszy niż cp-in-a-loop (lub kilka równoległych wywołań cp).


5

Aby użyć kopiowania xargsdo katalogów za pomocą symboli wieloznacznych w systemie Mac OS, jedynym rozwiązaniem, które działało dla mnie ze spacjami w nazwie katalogu, jest:

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

Gdzie testjest plik do skopiowania
I ./fs*/*katalogi do skopiowania

Problem polega na tym, że xargs widzi spacje jako nowy argument, rozwiązania zmiany znaku separatora za pomocą -dlub -Eniestety nie działają poprawnie w systemie Mac OS.


4

Jeśli chcesz to zrobić bez polecenia rozwidlonego:

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


2

Zasadniczo równoważne z odpowiedzią xargs, ale w przypadku, gdy chcesz wykonać równoległe:

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

Na przykład, aby skopiować plik1 do wszystkich podkatalogów bieżącego folderu (w tym rekurencji):

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

Uwaga: Prawdopodobnie zapewnia to jedynie zauważalne zwiększenie prędkości w bardzo szczególnych przypadkach użycia, np. Jeśli każdy katalog docelowy jest odrębnym dyskiem.

Jest również funkcjonalnie podobny do argumentu „-P” dla xargs.


0

Nie, nie możesz.

Wielokrotnie odkryłem, że mogę skorzystać z tej funkcji, dlatego stworzyłem własne narzędzie, aby to dla mnie zrobić.

http://github.com/ddavison/branch

dość proste -
branch myfile dir1 dir2 dir3


Często zdarzają się sytuacje, w których napisałbym własny skrypt, ale obecnie używam tak wielu maszyn, że utrzymywanie ich wszystkich w synchronizacji wydaje się dużym problemem. Gdyby tylko istniał sposób na zamontowanie katalogu internetowego w chmurze, /ena przykład tylko raz na każdej maszynie, mógłbym pisać własne narzędzia i przechowywać je na zawsze.
Evgeni Sergeev

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

1
A może trochę wyjaśnienia?
min.

To faktycznie działa, ale wyjaśnienie byłoby świetne
Declex

0

Załóżmy, że chcesz skopiować fileName.txtdo wszystkich podkatalogów w bieżącym katalogu roboczym.

  1. Uzyskaj wszystkie nazwy podkatalogów lsi zapisz je w pliku tymczasowym, powiedz:allFolders.txt

    ls > allFolders.txt
  2. Wydrukuj listę i przekaż ją do polecenia xargs.

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

0

Innym sposobem jest użycie kota i tee w następujący sposób:

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

Myślę, że byłoby to dość nieefektywne, ponieważ zadanie zostanie podzielone na kilka procesów (jeden na miejsce docelowe), a dysk twardy zapisuje kilka plików jednocześnie na różnych częściach talerza. Jednak jeśli chcesz zapisać plik na kilku różnych dyskach, ta metoda prawdopodobnie byłaby dość wydajna (ponieważ wszystkie kopie mogłyby się odbywać jednocześnie).


0

Za pomocą skryptu bash

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

Głosowałem za tym. Pytanie konkretnie dotyczy rozwiązania niepętlowego.
Alex Telon

-1

jeśli chcesz skopiować wiele folderów do wielu folderów, możesz zrobić coś takiego:

echo dir1 dir2 dir3 | xargs -n 1 cp -r / ścieżka / toyourdir / {subdir1, subdir2, subdir3}


-1

Jeśli wszystkie katalogi docelowe pasują do wyrażenia ścieżki - tak jak wszystkie podkatalogi path/to- użyj tego findw kombinacji z cpnastępującymi:

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

Otóż ​​to.


Głosowałem za tym. Pytanie konkretnie dotyczyło rozwiązania nie do znalezienia.
Alex Telon

Dziękujemy za bycie tak dokładnym @AlexTelon. Chyba za tym tęskniłem. Mam nadzieję, że również byłeś konsekwentny i oddałeś głos negatywny na każdą inną odpowiedź używaną findw wątku.
Mig82

-2

Jeśli musisz sprecyzować, do których folderów skopiować plik, możesz połączyć find z jednym lub kilkoma greps. Na przykład, aby zastąpić dowolne wystąpienia pliku favicon.ico w dowolnym podfolderze, którego możesz użyć:

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

-3

Spowoduje to skopiowanie do bezpośrednich podkatalogów, jeśli chcesz wejść głębiej, dostosuj -maxdepthparametr.

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

Jeśli nie chcesz kopiować do wszystkich katalogów, mam nadzieję, że możesz filtrować katalogi, które Cię nie interesują. Przykład kopiowania do wszystkich folderów zaczynających się od a

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

Jeśli kopiujesz do dowolnego katalogu katalogów, będziesz potrzebować sugestii Roberta Gamble'a.


-3

Lubię kopiować plik do wielu katalogów jako takich: cp file1 /foo/; cp file1 /bar/; cp file1 /foo2/; cp file1 /bar2/ I kopiować katalog do innych katalogów: cp -r dir1/ /foo/; cp -r dir1/ /bar/; cp -r dir1/ /foo2/; cp -r dir1/ /bar2/

Wiem, że to tak, jakby wydawać kilka poleceń, ale działa dobrze, gdy chcę wpisać linię 1 i odejść na chwilę.


7
Na 6-letnie pytanie udzielono 15 innych odpowiedzi. Twoja odpowiedź musi być dość nowatorska. Moja opinia - nie jest.
Craig S. Anderson

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.