tags:

views:

335

answers:

9

I have 16,000 jpg's from a webcan screeb grabber that I let run for a year pointing into the back year. I want to find a way to grab every 4th image so that I can then put them into another directory so I can later turn them into a movie. Is there a simple bash script or other way under linux that I can do this.

They are named like so......

frame-44558.jpg

frame-44559.jpg

frame-44560.jpg

frame-44561.jpg

Thanks from a newb needing help.

+1  A: 

An easy way in perl (probably easily adaptable to bash) is to glob the filenames in an array then get the sequence number and remove those that are not divisible by 4

Something like this will print the files you need:

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

You can replace the print by a move...

This will work if the files are numbered in sequence even if the number of digits is not constant like file_9.jpg followed by file_10.jpg )

Pat
+3  A: 

One simple way is:

$ 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

Dustin
Maybe you should point out that the first line is not necessary, it just creates sample data...
Sklivvz
+2  A: 

Create a script move.sh which contains this:

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

Make it executable and then do this in the folder:

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

This takes the list of filenames, passes four at a time into move.sh, which then ignores the first three and moves the fourth into a new folder.

This will work even if the numbers are not exactly in sequence (e.g. if some frame numbers are missing, then using mod 4 arithmetic won't work).

Leigh Caldwell
ls *.jpg | xargs -n 10 ./copy.sh bash: /bin/ls: Argument list too longcp: cannot stat `0': No such file or directory
I made a mistake. There were 280,000 images :)
+1  A: 
seq -f 'frame-%g.jpg' 1 4 number-of-frames

…will print the names of the files you need.

Alexey Feldgendler
A: 

Just iterate over a list of files:

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

This is pretty cheesy, but it should get the job done. Assuming you're currently cd'd into the directory containing all of your files:

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

The sort -n is there assuming your filenames don't all have the same number of digits; otherwise ls will sort in lexical order where frame-123.jpg comes before frame-4.jpg and I don't think that's what you want.

Please be careful, back up your files before trying my solution, etc. I don't want to be responsible for you losing a year's worth of data.

Also, since I can't comment yet, note that this solution does handle files with spaces in the name, unlike most of the others. I know that wasn't part of the sample filenames, but it's easy to write shell commands that don't handle spaces safely, so I wanted to do that in this example.

masto
A: 

Given masto's caveats about sorting:

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

The thing I like about this solution is that everything's doing what it was designed to do, so it feels unixy to me.

+2  A: 

As suggested, you should use

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

to generate the list of filenames since 'ls' will fail on 280k files. So the final solution would be something like:

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

pjz
A: 

Seems to have worked. Couple of errors in my origonal post. There were actually 280,000 images and the naming was. /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

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

Which appears to have copied the images. 70-900 per day from the looks of it.

Now I'm running mencoder mf://*.jpg -mf w=640:h=480:fps=30:type=jpg -ovc lavc -lavcopts vcodec=msmpeg4v2 -nosound -o ../output-msmpeg4v2.avi

I'll let you know how the movie works out.

UPDATE: Movie did not work. Only has images from 2007 in it even though the directory has 2008 as well. 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

How can I modify my mencoder line so that it uses all the images?