Tuesday, March 21, 2006

squirrel-ling with Linux

Starting out with a fairly simple one although could not do it for about 30 minutes which included some distraction.

Problem at hand:
I have a few files in my directory, let's call it Vidz.
$ Vidz> ls
[Video] animal_intellience.wmv
[Video] babies.wmv
[Video] be_quite.wmv
[Video] funny_cats1.wmv
[Video] funny_cats.wmv
[Video] i_cant_dance.wmv
[Video] millions_for_inner_peace.wmv
[Video] moron_olympics.wmv
[Video] run_escape_jump.wmv
[Video] squirrel.wmv
[Video] super_woman.wmv
[Video] woman_at_the_best.wmv

Now, I do not want all these files to consume so much space on my disk so I decided to get rid of all of them (the good old rm). Well, almost all of them except [Video] squirrel.wmv.

Approach:
So the first command I (along with Ciju) tried is:
ls -1 \[Video]\ [!s]* | wc -l

I did not want to delete my squirrel so I chose to list the files first and if the correct files get selected by filter, I'll delete them.
The approach is nice and clean but the problem is that I did not notice there was another file starting with letter 's', that file being [Video] super_woman.wmv.

Next try was:
ls -1 \[Video]\ [!s][!q]* | wc -l

For some good reason, it did not work either. We could have worked why that was not working, but chose to stick to the task at hand rather than focussing our attention elsewhere. Basically, the reason is that it excludes files starting with 's' AND files with second character in name as 'q'. What we wanted is exclusion of files with first character as 's' and second as 'q'.

Next thing we tried was the good old, tried-and-tested mechanism: Google!
http://www.google.com/search?num=20&hl=en&lr=&q=bash+exclusion and then
http://www.google.com/search?q=bash+regular+expression
But we reached nowhere. So sad.

The approach we tried then was to read man bash. I hate doing this, but Ciju likes it. Anyway, we went down to the section sub-titled Pattern Matching and found some clues there. Weren't able to use the pattern matching operators for about 5 minutes so we read the man page carefully and found a line about setting extglob option.
Once we had set that option, we knew we were pretty close. Tried a few random combinations there:
ls -1 \[Video]\ !(?(sq))* | wc -l
and
ls -1 \[Video]\ !(?(sq))  | wc -l


Then it stuck, and Ciju tried:
ls -1 \[Video]\ !(@(sq)*) | wc -l

Aha! There we were. That was exactly what we wanted to do.
What that command means, I'll explain in parts:
@(sq)*: Select all the files which start with exactly the pattern 'sq'.
!(@(sq)*): Select all files other than those which start with exactly the pattern 'sq'.

The last thing to do was:
ls -1 \[Video]\ !(@(sq)*)
(Confirmation)
rm \[Video]\ !(@(sq)*)


By the way, our squirrel was this:
Hope you have a great time till the next post, fellas!

Labels: ,