Arquivo duplicado x vezes no shell de comando

22

Eu tento duplicar um arquivo de vídeo x vezes da linha de comando usando um loop for, tentei assim, mas não funciona:

for i in {1..100}; do cp test.ogg echo "test$1.ogg"; done
Preto
fonte
5
Seu único erro não é o echoque não deveria estar lá e o $1que deveria estar $i?
Julie Pelletier
se eu remover o eco e usar apenas test$1.ogg, ele diz: test.ogg e test.ogg são os mesmos arquivos , então parece que $ 1 não é reconhecido?
Preto
@ EdwardBlack: Parece que eu entendi mal suas necessidades. Essa solução não é adequada.
cuonglm
@JuliePelletier, droga, às vezes acontece comigo que eu escrevo acidentalmente em $1vez de $i, é cedo pela manhã, desculpe ... obrigado. Vou usar $xno futuro, em vez de$i
Preto

Respostas:

25

Seu código do shell tem dois problemas:

  1. O echonão deveria estar lá.
  2. A variável $iestá digitada incorretamente como $1no nome do arquivo de destino.

Para fazer uma cópia de um arquivo no mesmo diretório que o próprio arquivo, use

cp thefile thecopy

Se você inserir mais alguma coisa, por exemplo,

cp thefile theotherthing thecopy

assume-se que você deseja copiar thefilee theotherthingpara o diretório chamado thecopy.

No seu caso, ele procura especificamente um arquivo chamado test.ogge um nomeado echopara copiar para o diretório test$1.ogg.

O $1mais provável será expandir para uma sequência vazia. É por isso que, quando você exclui o echocomando, você obtém "test.ogg e test.ogg são os mesmos arquivos"; o comando que está sendo executado é essencialmente

cp test.ogg test.ogg

Provavelmente é um erro de digitação.

No final, você quer algo como isto:

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

Ou, como alternativa

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

Ou, usando tee:

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

Nota: Isso provavelmente funcionaria para 100 cópias, mas para milhares de cópias pode gerar um erro "lista de argumentos muito longa". Nesse caso, volte a usar um loop.

Kusalananda
fonte
12

Curto e preciso

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

ou melhor ainda

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

consulte uso do comando tee para obter mais ajuda.

Atualizar

como sugerido por @Gilles, usar teetem o defeito de não preservar nenhum metadado de arquivo. Para superar esse problema, talvez seja necessário executar o comando abaixo:

cp --attributes-only --preserve Source Target
Rahul
fonte
3
Isso é potencialmente mais rápido do que várias chamadas para cp(depende do tamanho do arquivo em relação à memória disponível), mas tem o defeito de não preservar nenhum metadado do arquivo.
Gilles 'SO- stop be evil' -
@ Gilles ohh, podemos superar isso?
Rahul
3
Você pode correr cp --attributes-onlydepois.
Gilles 'SO- stop be evil'
@Gilles obrigado, atualizei minha resposta conforme sua ajuda.
Rahul
FWIW nenhuma das outras respostas usadas cp -ppara preservar os metadados.
roaima 6/06
11
for i in {1..100}; do cp test.ogg "test_$i.ogg" ; done
coffeMug
fonte
1
Expansões variáveis ​​devem ser citadas.
cat
1

O comando a seguir copiará o arquivo.a 5 vezes:

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

Se você preferir dd (não é o mesmo que cp!):

$ seq 5 | xargs -I AA dd if=file.a of=fileAA.a
cy8g3n
fonte
0

Você não chamou a variável i ao copiar

use o script abaixo. Como testado, funcionou bem

for i in {1..10}; do cp -rvfp test.ogg test$i.ogg ;done
Praveen Kumar BS
fonte
3
É o mesmo que as duas respostas anteriores e um comentário, exceto (1) a pergunta faz cerca de 100, e sua resposta usa 10, (2) você adicionou desnecessariamente as -rvfopções cpe (3) você não citou sua expansão variável . (Observe também que é convencional ter um espaço entre símbolos de pontuação como ;e a palavra a seguir.) A adição da -popção é valiosa, mas (4a) já foi abordada (nos comentários) e (4b) sua resposta não é útil se você não explicar o que está fazendo.
Scott