Tuesday, August 4, 2009

Find gotcha

Not too sure if I can call this a bonafide 'gotcha,' but it is something to keep in mind.

It is a good idea to occasionally check your Unix system for orphaned files. Normally you do so by using find with the -nouser and -nogroup filters. You could do two separate searches, one for -nouser, and then one for -nogroup, but typically the two are combined in one find command. Now here is the gotcha:

find / -nouser -nogroup -print

If you search find "-nouser -nogroup" on Google you likely find some examples like the one above. The problem with it is that there is an implied and when two or more filters are used as in the example. It is the same as doing the following (explicitly):

find / -nouser -a -nogroup -print
or:
find / -nouser -and -nogroup -print

The examples above will only 'find' files that belong to 'nouser' and 'nogroup.' If a file matches -nouser, but not -nogroup, find will not display it. If a file exists that matches -nogroup, but not -nouser, it will not display. Find will only return results that meet both criteria. In order to find all orphaned files, you want to do an or:

find / -nouser -o -nogroup -print

Now go have some fun tracking down those orphaned files!

Monday, August 3, 2009

Getting rid of troublesome files with GNU find.

Ok, so this isn't that much of a problem these days for those who are running a GUI, but what about when X isn't available? Consider the following:

kermit@fastbox ~/tmp/work2 $ ls -l
total 4
-rw-r--r-- 1 kermit kermit 37 2009-08-03 21:04 -pesky

I got that file by doing:

kermit@fastbox ~/tmp/work2 $ echo "Haha, sucker"\! "Try and get rid of me"\! > -pesky

Now try and issue the rm command on the file -pesky and you will find that it doesn't work so well. What can you do? Well, you can do what Bash tells you, and do:

kermit@fastbox ~/tmp/work2 $ rm -f ./-pesky

Or if you read the man page for rm, you would know that you can also do:

kermit@fastbox ~/tmp/work2 $ rm -f -- -pesky #The '--' tells the shell there are no more options following.

But there is another interesting way to do this operation, and it will work with other kinds of problematic, persistent files as well. We will use find to nuke the file. First, you need to find the inode number of the file, by using ls with the -i flag:

kermit@fastbox ~/tmp/work2 $ ls -li
total 4
8339920 -rw-r--r-- 1 kermit kermit 37 2009-08-03 20:57 -pesky

In this case, the inode number is 8339920. Now we can tell find to find the file with that number. Once it finds it, we can -exec /bin/rm -f and remove it:

kermit@fastbox ~/tmp/work2 $ find . -inum 8339920 -exec /bin/rm -f {} \;
kermit@fastbox ~/tmp/work2 $ ls -l
total 0