Duplikuj plik x razy w powłoce poleceń

22

Próbuję zduplikować plik wideo x razy z wiersza poleceń za pomocą pętli for, próbowałem w ten sposób, ale to nie działa:

for i in {1..100}; do cp test.ogg echo "test$1.ogg"; done
czarny
źródło
5
Czy nie jest to twój jedyny błąd, echoktóry nie powinien tam być i $1który powinien być $i?
Julie Pelletier,
jeśli usunę echo i użyję tylko, test$1.oggto powie: test.ogg i test.ogg to te same pliki , więc wygląda na to, że 1 $ nie został rozpoznany?
Czarny
@EdwardBlack: Brzmi, jakbym źle zrozumiał twoje wymagania. To rozwiązanie nie jest odpowiednie.
cuonglm
@JuliePelletier, cholera, czasem zdarza mi się, że przypadkowo piszę $1zamiast $i, jest wcześnie rano, przepraszam ... dziękuję. Użyję $xw przyszłości zamiast$i
Black

Odpowiedzi:

25

Twój kod powłoki ma dwa problemy:

  1. Nie echopowinno tam być.
  2. Zmienna $ijest błędnie wpisana jak $1w nazwie pliku docelowego.

Aby utworzyć kopię pliku w tym samym katalogu, co sam plik, użyj

cp thefile thecopy

Jeśli wstawisz coś jeszcze, np

cp thefile theotherthing thecopy

wtedy zakłada się, że chcesz skopiować thefilei theotherthingdo katalogu o nazwie thecopy.

W twoim przypadku szuka on pliku o nazwie test.oggi nazwanego echodo skopiowania do katalogu test$1.ogg.

$1Najprawdopodobniej rozszerzyć na pusty ciąg. Dlatego po usunięciu echopolecenia otrzymujesz „test.ogg i test.ogg to te same pliki”; wykonywane polecenie jest zasadniczo

cp test.ogg test.ogg

To prawdopodobnie błąd.

Na koniec chcesz coś takiego:

for i in {1..100}; do cp test.ogg "test$i.ogg"; done

Lub jako alternatywa

i=0
while (( i++ < 100 )); do
  cp test.ogg "test$i.ogg"
done

Lub używając tee:

tee test{1..100}.ogg <test.ogg >/dev/null

Uwaga: Najprawdopodobniej działałoby to dla 100 kopii, ale dla tysięcy kopii może wygenerować błąd „zbyt długiej listy argumentów”. W takim przypadku powróć do korzystania z pętli.

Kusalananda
źródło
12

Krótki i precyzyjny

< test.ogg tee test{1..100}.ogg

a nawet lepiej

tee test{1..100}.ogg < test.ogg >/dev/null

zobacz tee wykorzystanie polecenia , aby uzyskać pomoc.

Aktualizacja

jak sugeruje @Gilles, użycie teema wadę polegającą na tym, że nie zachowuje żadnych metadanych pliku. Aby rozwiązać ten problem, może być konieczne uruchomienie polecenia poniżej:

cp --attributes-only --preserve Source Target
Rahul
źródło
3
Jest to potencjalnie szybsze niż wielokrotne wywołania do cp(zależy od rozmiaru pliku w stosunku do dostępnej pamięci), ale ma tę wadę, że nie zachowuje żadnych metadanych pliku.
Gilles „SO- przestań być zły”
@Gilles, och, czy możemy to przezwyciężyć?
Rahul,
3
Możesz biegać cp --attributes-onlypóźniej.
Gilles „SO- przestań być zły”
@Gilles dzięki, zaktualizowałem moją odpowiedź zgodnie z twoją pomocą.
Rahul,
FWIW żadna z pozostałych odpowiedzi nie posłużyła cp -pdo zachowania metadanych.
roaima
11
for i in {1..100}; do cp test.ogg "test_$i.ogg" ; done
kubek kawy
źródło
1
Należy podać zmienne rozszerzenia.
kot
1

Następujące polecenie skopiuje plik. A 5 razy:

$ seq 5 | xargs -I AA cp file.a fileAA.a

Jeśli wolisz dd (nie to samo co cp!):

$ seq 5 | xargs -I AA dd if=file.a of=fileAA.a
cy8g3n
źródło
0

Nie wywołałeś zmiennej i podczas kopiowania

użyj poniżej skryptu. Po przetestowaniu działało dobrze

for i in {1..10}; do cp -rvfp test.ogg test$i.ogg ;done
Praveen Kumar BS
źródło
3
Jest to to samo, co dwie poprzednie odpowiedzi i komentarz, z wyjątkiem tego, że (1) pytanie zawiera około 100, a twoja odpowiedź wykorzystuje 10, (2) niepotrzebnie dodałeś -rvfopcje cpi (3) nie podałeś swojego rozszerzenia zmiennej . (Zwróć również uwagę, że konwencjonalne jest umieszczanie spacji między symbolami interpunkcyjnymi, takimi jak ;i następującym słowem.) Dodanie -popcji jest cenne, ale (4a) zostało już rozwiązane (w komentarzach) i (4b) twoja odpowiedź nie jest przydatne, jeśli nie wyjaśnisz, co robisz.
Scott