Jak skopiować plik do wielu folderów za pomocą wiersza polecenia?

67

Próbowałem skopiować plik test.txtdo wielu katalogów za pomocą jednego polecenia:

cp ~/test.txt ~/folder1 ~/folder2

Ale mi się nie udało. Czy można to zrobić za pomocą jednego polecenia, aby móc skopiować plik lub nawet folder do wielu katalogów?

nux
źródło
Nie łatwo. Warto zajrzeć do „rsync”, aby skutecznie zaktualizować wiele istniejących kopii folderu
Thorbjørn Ravn Andersen
3
Spróbuj nauczyć się skryptu bash. Może być bardzo przydatny:for dest in folder1 folder2; do cp ~/test.txt ~/"$dest"; done
Shahbaz
Ani jednego polecenia, ale może po prostu pomóc niektórym ludziom, którzy się tu natkną:cp ~/test.txt ~/folder1 && cp ~/test.txt ~/folder2
Manu Järvinen,
Duplikat stackoverflow.com/a/195972/2097284 .
Camille Goudeseune,

Odpowiedzi:

71

cpmożna kopiować z wielu źródeł, ale nie można kopiować do wielu miejsc docelowych. Zobacz man cpwięcej informacji.

Jedyne znane mi polecenie bash, które może kopiować / zapisywać do wielu miejsc docelowych, to tee.

Możesz użyć go w swoim przypadku w następujący sposób:

tee ~/folder1/test.txt ~/folder2/test.txt < ~/test.txt

Zauważ, że teezapisuje również dane wejściowe na standardowe wyjście (standardowe wyjście). Jeśli więc tego nie chcesz, możesz temu zapobiec, przekierowując standardowe wyjście /dev/nullw następujący sposób:

tee ~/folder1/test.txt ~/folder2/test.txt < ~/test.txt >/dev/null
Radu Rădeanu
źródło
10
Sprytnie, to oszustwo! :)
terdon
5
+1, sprytne! A jeśli używasz również >/dev/nullplików binarnych, nie psując terminala ...
Rmano
1
+1 dla ciebie, twój zawsze ma człowiek :), ale co, jeśli chcę skopiować katalog?
nux
2
@nux Nie zapomnij użyć -ropcji z cpw przypadku katalogów
Radu Rădeanu,
4
@nux: w teeprzeciwieństwie do cpkopiowania tylko zawartości pliku, ignorując jego tryb, własność, znaczniki czasu. Aby uniknąć powtarzania nazwy pliku:f=text.txt; <~/$f tee ~/folder1/$f > ~/folder2/$f
jfs
61

Innym sposobem uzyskania kopii do wielu lokalizacji jest następujące polecenie:

find dir1 dir2 -exec cp file.txt {} \;

Jeśli katalog 1 lub katalog 2 mają podkatalogi, w których nie chcesz kopiować pliku, dodaj -maxdepth 0opcję:

find dir1 dir2 -maxdepth 0 -exec cp file.txt {} \;

Zauważ, że ten zastąpi każdy plik dir1i dir2z file.txt„s zawartości, oprócz kopiowania go. Aby kopiować tylko file.txtbez wpływu na inne pliki w tych katalogach, powiedz, findaby działały tylko na katalogach:

find dir1 dir2 -type d -exec cp file.txt {} \;
Sylvain Pineau
źródło
4
Fajne rozwiązanie! Wydaje mi się doskonalszy niż z tee.
Danatela
1
Rzeczywiście, żadne przekierowanie nie jest zaangażowane i nadal jest to jedno polecenie.
Sylvain Pineau
2
@SylvainPineau W rzeczywistości są 3: jeden jest findi dwa razy (w tym przypadku) cp. Nie mówiąc już, że findpotrzeba dużo czasu.
Radu Rădeanu
3
Jeśli definicja „polecenia” jest wywołaniem „exec”, być może, ale w mojej książce jest to „jedno polecenie”.
kojiro
2
Wracam do tego, więc pomyślałem, że powinienem wyrazić opinię: D
Jonathan
31

Komenda

cp ~/test.txt ~/folder1 ~/folder2

próbuje skopiować dwa pliki ( ~/test.txti ~/folder1) do miejsca docelowego folder2. (A jeśli ~/folder2istnieje i jest katalogiem, pojawi się ostrzeżenie „pominięcie katalogu”).

Jeśli chcesz wykonać wiele kopii pliku test.txt, musisz użyć pętli lub wielu poleceń ...

for i in ~/folder1 ~/folder2; do cp  ~/test.txt $i; done 

(... i bądź ostrożny, jeśli spacje są osadzone w nazwach plików, musisz zacytować).

Aby skopiować całe katalogi, musisz użyć -ropcji:

for i in ~/folder1 ~/folder2; do cp -r ~/folder3 $i; done

spowoduje to utworzenie ~/folder1/folder3i uwzględnienie ~/folder2/folder3wszystkich plików.

Rmano
źródło
1
Dla przechodzącego czytnika: Zgodnie ze specyfikacją , pętla for jest poleceniem złożonym. Dlatego jest to nadal jedno polecenie i spełnia wszystkie wymagania dla pytania.
kojiro
@nux, nie zgadzam się na poprawki. 1) dwie wielkie litery są błędne, moim zamiarem było przeplatanie poleceń w zdaniu. 2) elipsa jest kwestią stylu; proszę wpuść mój styl.
Rmano,
1
ok, przepraszam stary, myślałem, że będzie lepiej.
nux
w moim systemie nie zapisuje folderu3 jako ~ / folder1 / folder3, ale raczej kopiuje wszystko z folderu3 do
folderu 1
23

Możesz utworzyć skrypt pomocy lub możesz to zrobić za xargspomocą funkcji drukowania (w tym przypadku echo):

echo firstDir secondDir | xargs -n 1 cp test

Spowoduje to, że każdy katalog będzie argumentem cpfunkcji, wykorzystując plik testowy jako parametr.

Evandro Silva
źródło
Jest to prawdopodobnie najlepsza / najbardziej bezpośrednia odpowiedź na pytanie
Bryson S.,
7

Po długich poszukiwaniach działa również jak Urok!

for dir in *; do [ -d "$dir" ] && cp /path/file.txt "$dir" ; done

Spowoduje to skopiowanie pliku.txt do każdego katalogu w bieżącej lokalizacji w terminalu.

for dir in *; do [ -d "$dir" ] && cp -rf /path/folder "$dir" ; done

Spowoduje to skopiowanie folderu do każdego podkatalogu w bieżącej lokalizacji w terminalu.

Podzielam to, mam nadzieję, że pomaga także innym.

nux
źródło
Za zshpomocą for i in *(/); ...można przewijać wszystkie podkatalogi, aby uniknąć [ -d ...testu. Rozszerzone globowanie jest jednym z powodów, dla których lubię to bash.
Rmano,
czy możesz ponownie
skorygować
1
W zsh, pierwsze polecenie tej odpowiedzi można uprościć jako for dir in *(/); do cp /path/file.txt "$dir"; done. Zobacz zsh.sourceforge.net/Intro/intro_2.html
Rmano
5
Możesz wyeliminować test w dowolnej powłoce Bourne'a za pomocąfor dir in */;
Henk Langeveld
@nux Działa to naprawdę dobrze, a polecenie jest bardzo łatwe do wykonania. Należy głosować znacznie wyżej!
nukeguy
1

Jeśli chcesz skopiować plik test.txt w każdym katalogu w / tmp / target / ...

utwórz środowisko testowe:

mkdir /tmp/target
cd /tmp/target
mkdir -v {folder1,folder2,folder3}
touch test.txt

skopiuj to:

find * -maxdepth 0 -type d -exec cp -vi test.txt {} \;
matowy
źródło
0

Pomyślałem, że można zmienić odpowiedź na Sylvain Pineau

gdzie dir1i dir2nie ma ich w bieżącym katalogu.

find ./ -maxdepth 2 -type d -name dir1 -exec cp file.txt {} \;

tutaj find szuka dir1dwóch poziomów głębokości lub możesz pominąć -maxdepthparametr, aby znaleźć dir1we wszystkich folderach w bieżącym katalogu i poniżej niego.

Joshi
źródło