5 votos

Para el lazo con el find de unix

Tratando de hacer a una masa convertir de M4A a OGG en una colección grande de la música, tengo:

#!/bin/sh
for i in `find /home/family/Music -name *.m4a -print0`
   #do ffmpeg -i "$i" -acodec libvorbis -aq 6 -vn -ac 2 "$i.ogg";
   do echo $i
done

Todos los archivos tienen espacios en sus nombres, la salida para el de arriba muestra un archivo como este:

/home/family/Music/The
Kooks/Inside
In
_
Inside
Out/06
You
Don't
Love
Me.m4a

¿Cada espacio marca una nueva línea, pensé que -print0 sería solucionar este problema?

8voto

muru Puntos 43315

Utilizar xargs con -0 la opción, o utilizar find del propio exec opción:

find /home/family/Music -name '*.m4a' -exec ffmpeg -i "{}" -acodec libvorbis -aq 6 -vn -ac 2 "{}.ogg" \;
# or:
find /home/family/Music -name '*.m4a' -print0 | xargs -0 -i ffmpeg -i {} -acodec libvorbis -aq 6 -vn -ac 2 {}.ogg

Tenga en cuenta que en ambos casos (y en el comando original), x.m4a se convertirá en x.m4a.ogg .

1voto

g_p Puntos 6812

Esto puede ser la solución de lo que quieres

#!/bin/bash    
find  /home/family/Music -type f -name '*.m4a' -print0 | while IFS= read -r -d '' i; 
  do
   #do ffmpeg -i "$i" -acodec libvorbis -aq 6 -vn -ac 2 "$i.ogg"; 
   echo $i
done

0voto

Stewart Puntos 1385

Esa es una de las razones por las que nunca uso un for bucle para iterar a través de un comando cuya salida puede contener espacios. Especialmente si la salida es una lista de nombres de archivo que puede contener cualquier cosa , excepto / y \0. Usted ha caído en bash escollo número 1. Siempre use while lugar. Para asegurarse de que funciona con todos los nombres de archivo, incluyendo aquellos con espacios, saltos de línea, tabulaciones, barras o cualquier otros caracteres extraños, utilice esto:

find /home/family/Music -name '*.m4a' -print0 | while IFS= read -r -d '' file; do
     ffmpeg -i "$file" -acodec libvorbis -aq 6 -vn -ac 2 "${file%.m4a}.ogg";
done

Explicación

  • Tenga en cuenta que he citado *.mp4a que asegura que bash no se expanda antes de pasar a find. Esto es importante para los casos donde tienes los archivos que coinciden con ese pegote en el directorio actual.

  • El -print0, como usted probablemente sabe, las causas find a separar sus resultados con \0 en lugar de saltos de línea.

  • IFS= : Establece el campo de entrada de caracteres para nada, asegurándose de que ninguna palabra después de la división de tener lugar.

  • while read -r -d '' file: Esto va a iterar a través de los resultados, el ahorro de cada una de la $file, como for file in $(command). Las opciones son (de help read):

     -r     do not allow backslashes to escape any characters
     -d delim   continue until the first character of DELIM is read, rather
        than newline
    

    Ajuste el delimitador a la cadena vacía (-d '') hace read jugar bien con encontrar la -print0.

  • "${file%.mp3}.ogg"; : Esto es simplemente para quitar el .m4a de sufijo y reemplazarlo con .ogg así que usted consigue foo.ogg en lugar de foo.m4a.ogg.

El resto es el mismo que había intentado, así que supongo que usted lo entiende.

EnMiMaquinaFunciona.com

EnMiMaquinaFunciona es una comunidad de administradores de sistemas en la que puedes resolver tus problemas y dudas.
Puedes consultar las preguntas de otros sysadmin, hacer tus propias preguntas o resolver las de los demás.

Powered by: