Archivo duplicado x veces en el shell de comandos

22

Intento duplicar un archivo de video x veces desde la línea de comando usando un bucle for, lo he intentado así, pero no funciona:

for i in {1..100}; do cp test.ogg echo "test$1.ogg"; done
Negro
fuente
55
¿No es su único error el echoque no debería estar allí y el $1que debería estar $i?
Julie Pelletier
si elimino el eco y solo lo uso test$1.ogg, dice: test.ogg y test.ogg son los mismos archivos , por lo que parece que $ 1 no se reconoce.
Negro
@EdwardBlack: Parece que entendí mal tus requisitos. Esa solución no es adecuada.
Cuonglm
@JuliePelletier, maldición, a veces me sucede que escribo de manera accidental en $1lugar de $i, es temprano en la mañana, lo siento ... gracias. Lo usaré $xen el futuro en lugar de$i
Black

Respuestas:

25

Su código de shell tiene dos problemas:

  1. El echono debería estar allí.
  2. La variable $iestá mal escrita como $1en el nombre del archivo de destino.

Para hacer una copia de un archivo en el mismo directorio que el archivo en sí, use

cp thefile thecopy

Si inserta algo más allí, por ejemplo

cp thefile theotherthing thecopy

entonces se supone que desea copiar thefiley theotherthingen el directorio llamado thecopy.

En su caso, busca específicamente un archivo llamado test.oggy uno llamado echopara copiar en el directorio test$1.ogg.

Lo $1más probable es que se expanda a una cadena vacía. Es por eso que, cuando elimina el echocomando, obtiene "test.ogg y test.ogg son los mismos archivos"; el comando que se ejecuta es esencialmente

cp test.ogg test.ogg

Esto es probablemente un error.

Al final, quieres algo como esto:

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

O como alternativa

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

O, usando tee:

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

Nota: Esto probablemente funcionaría para 100 copias, pero para miles de copias puede generar un error de "lista de argumentos demasiado larga". En ese caso, vuelva a usar un bucle.

Kusalananda
fuente
12

Corto y preciso

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

o incluso mejor hacerlo

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

vea el uso del comando tee para más ayuda.

Actualizar

según lo sugerido por @Gilles, el uso teetiene el defecto de no preservar ningún metadato de archivo. Para superar ese problema, es posible que deba ejecutar el siguiente comando después de eso:

cp --attributes-only --preserve Source Target
Rahul
fuente
3
Esto es potencialmente más rápido que las llamadas múltiples cp(depende del tamaño del archivo en relación con la memoria disponible), pero tiene el defecto de no preservar ningún metadato de archivo.
Gilles 'SO- deja de ser malvado'
@ Gilles ohh, ¿podemos superar eso?
Rahul
3
Puedes correr cp --attributes-onlydespués.
Gilles 'SO- deja de ser malvado'
@Gilles gracias, actualicé mi respuesta según su ayuda.
Rahul
FWIW ninguna de las otras respuestas utilizadas cp -ppara preservar los metadatos tampoco.
roaima 06/0617
11
for i in {1..100}; do cp test.ogg "test_$i.ogg" ; done
taza de cafe
fuente
1
Las expansiones variables deben ser citadas.
gato
1

El siguiente comando copiará el archivo. A 5 veces:

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

Si prefiere dd (¡no es lo mismo que cp!):

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

No ha llamado a la variable i al copiar

use el siguiente script. Según lo probado, funcionó bien

for i in {1..10}; do cp -rvfp test.ogg test$i.ogg ;done
Praveen Kumar BS
fuente
3
Esto es lo mismo que dos respuestas anteriores y un comentario, excepto (1) la pregunta hace alrededor de 100, y su respuesta usa 10, (2) ha agregado innecesariamente las -rvfopciones cpy (3) no ha citado su expansión variable . (También tenga en cuenta que es convencional tener un espacio entre los signos de puntuación como ;y la siguiente palabra.) La adición de la -popción es valiosa, pero (4a) ya se ha abordado (en comentarios), y (4b) su respuesta no es útil si no explicas lo que estás haciendo.
Scott