tutorial scripts script lenguaje espaƱol ejemplos comandos bash scripting

scripts - bin bash



Agarrando cada cuarto archivo (8)

Tengo 16,000 jpg de un capturador de páginas web que dejé correr durante un año señalando el año pasado. Quiero encontrar una manera de tomar cada 4ta imagen para luego poder ponerlas en otro directorio para luego poder convertirlas en una película. ¿Hay un script bash simple o de otra manera en Linux que pueda hacer esto?

Ellos son nombrados así ......

frame-44558.jpg

frame-44559.jpg

frame-44560.jpg

frame-44561.jpg

Gracias de un nuevo que necesita ayuda.

Parece que funcionó. Un par de errores en mi publicación original. En realidad, había 280,000 imágenes y el nombre era. /home/baldy/Desktop/webcamimages/webcam_2007-05-29_163405.jpg /home/baldy/Desktop/webcamimages/webcam_2007-05-29_163505.jpg /home/baldy/Desktop/webcamimages/webcam_2007-05-29_163605.jpg

Corrí. cp $ (ls | awk ''{nr ++; if (nr% 10 == 0) print $ 0}'') ../newdirectory/

Que parece haber copiado las imágenes. 70-900 por día por lo que parece.

Ahora ejecuto el mencoder mf: //*.jpg -mf w = 640: h = 480: fps = 30: tipo = jpg -ovc lavc -lavcopts vcodec = msmpeg4v2 -nosound -o ../output-msmpeg4v2.avi

Te dejaré saber cómo funciona la película.

ACTUALIZACIÓN: la película no funcionó. Solo tiene imágenes de 2007, aunque el directorio también tiene 2008. webcam_2008-02-17_101403.jpg webcam_2008-03-27_192205.jpg webcam_2008-02-17_102403.jpg webcam_2008-03-27_193205.jpg webcam_2008-02-17_103403.jpg webcam_2008-03-27_194205.jpg webcam_2008-02-17_104403.jpg webcam_2008 -03-27_195205.jpg

¿Cómo puedo modificar mi línea de mencoder para que use todas las imágenes?


Crea un script move.sh que contenga esto:

#!/bin/sh mv $4 ../newdirectory/

Hazlo ejecutable y luego hazlo en la carpeta:

ls *.jpg | xargs -n 4 ./move.sh

Esto toma la lista de nombres de archivo, pasa cuatro a la vez en move.sh, que luego ignora los tres primeros y mueve el cuarto a una nueva carpeta.

Esto funcionará incluso si los números no están exactamente en secuencia (por ejemplo, si faltan algunos números de cuadro, entonces el uso de mod 4 arithmetic no funcionará).


Dadas las advertencias de Masto sobre la clasificación:

ls | sed -n ''1~4 p'' | xargs -i mv {} ../destdir/

Lo que más me gusta de esta solución es que todo está haciendo lo que está diseñado para hacer, por lo que se siente unixy para mí.


Simplemente itere sobre una lista de archivos:

files=( frame-*.jpg ) i=0 while [[ $i -lt ${#files} ]] ; do cur_file=${files[$i]} mungle_frame $cur_file i=$( expr $i + 4 ) done


Una forma fácil en Perl (probablemente fácilmente adaptable a bash) es agrupar los nombres de los archivos en una matriz, luego obtener el número de secuencia y eliminar aquellos que no son divisibles por 4

Algo como esto imprimirá los archivos que necesita:

ls -1 /path/to/files/ | perl -e ''while (<STDIN>) {($seq)=/(/d*)/.jpg$/; print $_ if $seq && $seq % 4 ==0}''

Puede reemplazar la impresión por un movimiento ...

Esto funcionará si los archivos están numerados en secuencia, incluso si la cantidad de dígitos no es constante, como file_9.jpg seguido de file_10.jpg )


Una forma simple es:

$ touch a b c d e f g h i j k l m n o p q r s t u v w x y z $ mv $(ls | awk ''{nr++; if (nr % 4 == 0) print $0}'') destdir


seq -f ''frame-%g.jpg'' 1 4 number-of-frames

... imprimirá los nombres de los archivos que necesita.


Esto es bastante cursi, pero debería hacer el trabajo. Suponiendo que actualmente está copiado en el directorio que contiene todos sus archivos:

mkdir ../outdir ls | sort -n | while read fname; do mv "$fname" ../outdir/; read; read; read; done

El sort -n está ahí suponiendo que sus nombres de archivo no tienen el mismo número de dígitos; de lo contrario, ls en orden léxico donde frame-123.jpg viene antes de frame-4.jpg y no creo que eso sea lo que quieres.

Tenga cuidado, haga una copia de seguridad de sus archivos antes de probar mi solución, etc. No quiero ser responsable de perder los datos de un año.

Tenga en cuenta que esta solución maneja los archivos con espacios en el nombre, a diferencia de la mayoría de los demás. Sé que no era parte de los nombres de archivo de muestra, pero es fácil escribir comandos de shell que no manejen espacios de forma segura, así que quería hacer eso en este ejemplo.


Como se sugiere, debes usar

seq -f ''frame-%g.jpg'' 1 4 number-of-frames

para generar la lista de nombres de archivos dado que ''ls'' fallará en 280k archivos. Entonces la solución final sería algo así como:

for f in `seq -f ''frame-%g.jpg'' 1 4 number-of-frames` ; do mv $f destdir/ done