Find the directories containing the most files

I needed to find the directories containing the most files, so I whipped up this bit of voodoo at the command line:

find . -type f -print | perl -na -F/ -e 'while (pop @F && @F) { print join ("/", @F)."n"; }' | sort | uniq -c | sort -n

This will count the number of files in each directory beneath your current directory, and print out those directories in ascending order by the number of files they contain. It will also print totals for parent directories–if “foo/bar” has one file, “foo/baz” has two, and “foo/” itself has one, then the line for “foo” will be printed with the number four.

Handy for me, possibly handy for you as well. This works in Linux and Mac OS X Leopard.

Mac Software Bundles Aplenty

There are at least five different promos going on for various Mac shareware right now. If you're part of the Mac fold, I'd say you pretty much “gotta” check out the first two; the other three are cool, but less so.

This is part of what, in my opinion, sets the Mac experience apart from that of other platforms: there is a vibrant ecosystem of independent, small-scale development shops producing stunningly-good apps for free, or for low cost. (Although there's clearly lots of independent development going on for other platforms, there seems to be a much greater variability in the quality.) Promotion events like these give good advertising for those smaller development shops, and give Mac users the chance to try and use good software that they might never have even heard of before. I really think it's a win-win.

I've listed them below, ordered by descending perceived awesomeness.

  1. MacHeist – In its second year, you act as a “spy” and solve mission-related puzzles about once a week. Free apps await after you complete each mission, as well as incremental discounts on a large bundle that will go on sale at the end. This is terrifically fun; I can't recommend it highly enough.

Technorati Tags:
, ,

  1. MacUpdate Bundle – Bundle of 7 applications on sale over the next week or so at roughly 90% off the total retail price. Three additional apps will “unlock” and become part of the bundle if sales are high enough.
  2. MacSanta – Several apps listed each day from now through Christmas at 20% off. Apps from previous days available at 10% off. Lots of variety here, but the discount isn't as good as the previous two.
  3. Give Good Food to your Mac – Piece together your own bundle of apps, with a discount percentage that increases based on how many apps you buy. I didn't find any of the apps particularly compelling, but you might disagree. Ends 12/10.
  4. TheMacPak Santa's Stocking – A bundle of five apps and two games at a pretty steep discount, available through 12/10. The only problem: you don't know what the apps are before you buy them!

Using the iPhone for Presence Detection with MisterHouse… almost

I've got a reasonably interesting setup of MisterHouse (a nifty Perl-based home automation program) running on a Linux machine upstairs, that does stuff like turn on lights automatically when it's getting dark or when I enter a room, turn lights off when there hasn't been any activity in a room after a predefined time, and so forth. Maybe I'll post more on that later.

One thing that's missing, though, is a good way for the server to know if I'm home. As I mentioned, there are some lights that come on automatically when it gets dark, but some of that is really kind of a waste of energy if I'm not actually home. (Of course, some lighting would be good so our dogs can get around, but I think they'd be fine with a smidge fewer lumens than we expect.)

One suggestion that I've seen is to install a battery powered motion sensor (like this one somewhere inconspicuous in your car. This broadcasts on the X10 wireless spectrum, and would likely be within range if your car is at home. It broadcasts “motion” and “still” (i.e. “no motion”) signals, as well as “light” and “dark”, so it will send signals even if it doesn't see movement. Then, presumably, you can configure MisterHouse so that, if it notices these wireless signals, it assumes that you are home.

However, this solution has a couple of unpleasant attributes:

  1. It requires you to stick a motion sensor in your car
  2. Motion sensors are ugly
  3. It's not going to transmit continuously enough for your home automation system to know you're “still” there
  4. There's no way you'd be able to pick up chicks in your ride if they see ugly motion sensors, plus they'd probably think they were cameras and get all creeped out

Another way you could do it (that would be fantastically cool) would be with RFID. If, somehow, you carried an RFID tag around with you most of the time, a long-range RFID reader could tell when you're home and alert MisterHouse appropriately. This would be sweet. One idea (and I don't know if this is my own, or one that I read somewhere) is to put the RFID tag on your keychain, and then embed a reader in a hook where you hang your keys when you come in the door. That would work great, as long as you are diligent about putting your keys there as soon as you walk in the door. Me, that's not how I operate. As soon as I walk in the door, I like to baseball-pitch my keys into a neighboring town and/or state for convenience when I'm about to leave again. Oh, and also, I don't have any RFID stuff yet, so I'd have to buy some and learn it and integrate it. Devil you know and all that.

So, after getting my (awesome) iPhone and pairing it with my wireless network, I realized there was another possibility–if the phone is currently on the network, that's a pretty good indication that I'm home. My phone is always on, and always with me, so it seems there's a fairly low likelihood of false positives and false negatives. My basic plan is to try to ping the phone on some frequent basis, maybe once per minute, and see if it responds. If it does, then tell Misterhouse that I'm home.

One caveat: I use DHCP on my home network, so it's theoretically possible that I could have different IP addresses each time I join the network. Since I hacked my Linksys WRT54G to use DD-WRT, I could configure the router to give my phone a static DHCP assignment. That's too easy, though, so I decided I'd try to learn a bit and ping the phone by its MAC address (which is hardware-specific and never changes) instead of its IP address. Your system maintains a mapping from MAC address to IP address internally. This mapping is done via a protocol called ARP.

First, I looked in my phone settings to determine my MAC address. If you're a lucky iPhone user, too, you can find your MAC address at Settings > General > About > Wi-Fi Address, like so:

From this, I know that my iPhone's MAC address starts with 00:1B:63.

Next, I logged into my Linux machine upstairs (the one running MisterHouse) and sent a “ping” to the network broadcast address, which tells all hosts to respond:

[jason@assmonkey ~]$ ping -b 192.168.1.255
WARNING: pinging broadcast address
PING 192.168.1.255 (192.168.1.255) 56(84) bytes of data.
64 bytes from 192.168.1.101: icmp_seq=1 ttl=64 time=53.5 ms
64 bytes from 192.168.1.158: icmp_seq=1 ttl=64 time=56.9 ms (DUP!)
64 bytes from 192.168.1.101: icmp_seq=2 ttl=64 time=77.4 ms
64 bytes from 192.168.1.158: icmp_seq=2 ttl=64 time=178 ms (DUP!)
64 bytes from 192.168.1.101: icmp_seq=3 ttl=64 time=101 ms
64 bytes from 192.168.1.158: icmp_seq=3 ttl=64 time=201 ms (DUP!)

--- 192.168.1.255 ping statistics ---
3 packets transmitted, 3 received, +3 duplicates, 0% packet loss, time 2000ms
rtt min/avg/max/mdev = 53.509/111.650/201.997/58.103 ms
[jason@assmonkey ~]$ 

This has the effect of filling in the ARP cache on your system with the MAC addresses of all machines that responded to the ping. Now, I can look in the cache with the following command:

[jason@assmonkey ~]$ /sbin/arp -a
? (192.168.1.158) at 00:1B:63:XX:XX:XX [ether] on eth0
Crap (192.168.1.1) at 00:18:39:XX:XX:XX [ether] on eth0
macbook (192.168.1.101) at 00:17:F2:XX:XX:XX [ether] on eth0
? (192.168.1.131) at 00:0F:1F:XX:XX:XX [ether] on eth0
[jason@assmonkey ~]$

Bingo! Since we know that the MAC address started with 00:1B:63, we can tell that its IP address is 192.168.1.158. Now, a good old-fashioned ping confirms that the phone is on the network:

[jason@assmonkey ~]$ ping 192.168.1.158
PING 192.168.1.158 (192.168.1.158) 56(84) bytes of data.
64 bytes from 192.168.1.158: icmp_seq=1 ttl=64 time=51.3 ms
64 bytes from 192.168.1.158: icmp_seq=2 ttl=64 time=2.61 ms

--- 192.168.1.158 ping statistics ---
2 packets transmitted, 2 received, 0% packet loss, time 1001ms
rtt min/avg/max/mdev = 2.619/26.964/51.310/24.346 ms
[jason@assmonkey ~]$

But, oh noes! A few minutes later, I retried the ping, and found this:

[jason@assmonkey ~]$ ping 192.168.1.158
PING 192.168.1.158 (192.168.1.158) 56(84) bytes of data.

--- 192.168.1.158 ping statistics ---
10 packets transmitted, 0 received, 100% packet loss, time 8999ms

[jason@assmonkey ~]$

The phone wasn't pingable anymore! I did some digging around, and came to the conclusion that the iPhone disconnects from the wireless network when you're not actively using it. This is probably done to conserve power. Unfortunately, though, this kind of defeats the point of the entire attempt, as I need the phone to be pingable on a continuous basis in order for my presence detection scheme to work.

So, that's why I put “almost” in the title. Anyone know a more clever way to do this?