GNU/Linux >> Tutoriales Linux >  >> Linux

¿Convertir `for File In` en `find` para que el script pueda aplicarse recursivamente?

Tengo esta idea de ejecutar un script bash para verificar algunas condiciones y usar ffmpeg para convertir todos los videos en mi directorio de cualquier formato a .mkv ¡y está funcionando muy bien!

El caso es que no sabía que un for file in loop no funciona recursivamente (https://stackoverflow.com/questions/4638874/how-to-loop-through-a-directory-recursively)

Pero apenas entiendo "tuberías" y espero ver un ejemplo y aclarar algunas dudas.

Tengo este escenario en mente que creo que me ayudaría mucho a entender.

Supongamos que tengo este fragmento de script bash:

for file in *.mkv *avi *mp4 *flv *ogg *mov; do
target="${file%.*}.mkv"
    ffmpeg -i "$file" "$target" && rm -rf "$file"
done

Lo que hace es, para el directorio actual, buscar cualquier *.mkv *avi *mp4 *flv *ogg *mov luego declare la salida para que su extensión sea .mkv luego, elimine el archivo original, luego la salida debe guardarse en la misma carpeta en la que se encuentra el video original.

  1. ¿Cómo puedo convertir esto para que se ejecute recursivamente? si uso find , donde declarar la variable $file ? ¿Y dónde deberías declarar $target? ? Son todos find ¿realmente frases ingeniosas? Realmente necesito pasar el archivo a una variable $file , porque aún tendré que ejecutar la verificación de condición.

  2. Y, suponiendo que (1) tenga éxito, ¿cómo asegurarse de que se cumpla el requisito "entonces la salida debe guardarse en la misma carpeta en la que se encuentra el video original"?

Respuesta aceptada:

Tienes este código:

for file in *.mkv *avi *mp4 *flv *ogg *mov; do
target="${file%.*}.mkv"
    ffmpeg -i "$file" "$target" && rm -rf "$file"
done

que se ejecuta en el directorio actual. Para convertirlo en un proceso recursivo, tiene un par de opciones. El más fácil (IMO) es usar find como sugeriste. La sintaxis para find es muy "no similar a UNIX", pero el principio aquí es que cada argumento se puede aplicar con condiciones AND u OR. Aquí, vamos a decir "Si este nombre de archivo coincide O ese nombre de archivo coincide, entonces imprímalo “. Los patrones de nombre de archivo están entrecomillados para que el shell no pueda controlarlos (recuerde que el shell es responsable de expandir todos los patrones sin comillas, por lo que si tenía un patrón sin comillas de *.mp4 y tenías janeeyre.mp4 en su directorio actual, el shell reemplazaría *.mp4 con la coincidencia y find vería -name janeeyre.mp4 en lugar de su -name *.mp4; empeora si *.mp4 coincide con varios nombres...). Los corchetes tienen el prefijo \ también para evitar que el shell intente activarlos como marcadores de subshell (podríamos citar los corchetes en su lugar, si lo prefiere:'(' ).

find . \( -name '*.mkv' -o -name '*avi' -o -name '*mp4' -o -name '*flv' -o -name '*ogg' -o -name '*mov' \) -print

La salida de esto debe alimentarse a la entrada de un while bucle que procesa cada archivo a su vez:

while IFS= read file    ## IFS= prevents "read" stripping whitespace
do
    target="${file%.*}.mkv"
    ffmpeg -i "$file" "$target" && rm -rf "$file"
done

Ahora todo lo que queda es unir las dos partes con un tubo | para que la salida de find se convierte en la entrada del while bucle.

Relacionado:¿Puede CloudMagic buscar el contenido de un archivo en Dropbox?

Mientras prueba este código, le recomiendo que prefije ambos ffmpeg y rm con echo para que pueda ver lo que sería ser ejecutado – y con qué caminos.

Aquí está el resultado final, incluido el echo declaraciones que recomiendo para probar:

find . \( -name '*.mkv' -o -name '*avi' -o -name '*mp4' -o -name '*flv' -o -name '*ogg' -o -name '*mov' \) -print |
    while IFS= read file    ## IFS= prevents "read" stripping whitespace
        do
            target="${file%.*}.mkv"
            echo ffmpeg -i "$file" "$target" && echo rm -rf "$file"
        done

Linux
  1. Cómo encontrar el paquete que proporciona un archivo específico en Linux

  2. ¿Por qué The Bash Script no reconoce los alias?

  3. Bash Script para eliminar el archivo más antiguo de una carpeta?

  4. ¿No puede obtener el código de salida correcto de un script?

  5. ¿Cómo evitar un script de Shell el Sigpipe que sería causado por el uso de un descriptor de archivo cerrado?

Si cambio los permisos en un archivo Tar, ¿se aplicará eso a los archivos que contiene?

¿Cómo sé el nombre del archivo de script en un script Bash?

Variable en Bash Script que mantiene su valor desde la última vez que se ejecutó

¿Cómo puedo copiar archivos recursivamente por extensión de archivo, preservando la estructura del directorio?

¿Cómo mostrar el contenido del archivo de forma recursiva?

¿Puede un archivo .sh ser malware?