Дублировать файл x раз в командной оболочке

22

Я пытаюсь скопировать видеофайл x раз из командной строки, используя цикл for, я пробовал это так, но это не работает:

for i in {1..100}; do cp test.ogg echo "test$1.ogg"; done
черный
источник
5
Разве ваша единственная ошибка не в том, echoчего не должно быть, и в том, $1что должно быть $i?
Джули Пеллетье
если я удаляю echo и использую только test$1.oggтогда, он говорит: test.ogg и test.ogg - это одни и те же файлы , поэтому кажется, что $ 1 не распознается?
Черный
@ EdwardBlack: Похоже, я неправильно понял ваши требования. Это решение не подходит.
cuonglm
@JuliePelletier, чёрт, иногда мне случается так, что я пишу случайно, $1а $iне раннее утро, извините ... спасибо. Я буду использовать $xв будущем вместо$i
Black

Ответы:

25

У вашего шелл-кода есть две проблемы:

  1. Там echoне должно быть.
  2. Переменная $iвводится с ошибкой, как $1в имени файла назначения.

Чтобы сделать копию файла в том же каталоге, что и сам файл, используйте

cp thefile thecopy

Если вы вставите что-нибудь еще туда, например

cp thefile theotherthing thecopy

тогда предполагается, что вы хотите скопировать thefileи theotherthingв каталог с именем thecopy.

В вашем случае он специально ищет файл с именем test.oggи именем, который echoнужно скопировать в каталог test$1.ogg.

$1, Скорее всего , расширится к пустой строке. Вот почему, когда вы удаляете команду echoиз команды, вы получаете «test.ogg и test.ogg - это одни и те же файлы»; выполняемая команда по существу

cp test.ogg test.ogg

Это, вероятно, опечатка.

В конце концов, вы хотите что-то вроде этого:

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

Или, как альтернатива

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

Или, используя tee:

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

Примечание. Скорее всего, это будет работать для 100 копий, но для тысяч копий может привести к ошибке «список аргументов слишком длинный». В этом случае вернитесь к использованию цикла.

Кусалананда
источник
12

Коротко и точно

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

или даже лучше сделать

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

см. использование команды tee для получения дополнительной помощи.

Обновить

как предлагает @Gilles, использование teeимеет дефект в том, что не сохраняет метаданные файла. Чтобы преодолеть эту проблему, вам может потребоваться выполнить команду ниже после этого:

cp --attributes-only --preserve Source Target
Рахул
источник
3
Это потенциально быстрее, чем множественные вызовы cp(зависит от размера файла относительно доступной памяти), но имеет недостаток - не сохранять метаданные файла.
Жиль "ТАК ... перестать быть злым"
@ Жиль, мы можем это преодолеть?
Рахул
3
Вы можете запустить cp --attributes-onlyпотом.
Жиль "ТАК - перестань быть злым"
@ Жиль спасибо, обновил мой ответ в соответствии с вашей помощью.
Рахул
FWIW ни один из других ответов также не использовался cp -pдля сохранения метаданных.
roaima
11
for i in {1..100}; do cp test.ogg "test_$i.ogg" ; done
coffeMug
источник
1
Переменные расширения должны быть указаны.
кот
1

Следующая команда скопирует file.a 5 раз:

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

Если вы предпочитаете dd (не то же самое, что cp!):

$ seq 5 | xargs -I AA dd if=file.a of=fileAA.a
cy8g3n
источник
0

Вы не вызвали переменную I во время копирования

используйте скрипт ниже. Как проверено это работало нормально

for i in {1..10}; do cp -rvfp test.ogg test$i.ogg ;done
Правин Кумар Б.С.
источник
3
Это то же самое, что два предыдущих ответа и комментарий, за исключением (1) вопрос задает около 100, а в вашем ответе используется 10, (2) вы излишне добавили -rvfопции cp, и (3) вы не в кавычках указали расширение переменной , (Также обратите внимание, что принято ставить пробел между символами пунктуации, такими как ;и следующее слово.) Добавление -pопции является полезным, но (4a) он уже был рассмотрен (в комментариях), а (4b) ваш ответ не является полезно, если вы не объясняете, что делаете.
Скотт