On may Unix variants, find first looks for current working directory before proceeding with what it was asked to find. Ubuntu 10.10 and Debian Squezze not affected and I did not check older versions, but debian 5.0.6 or Lenny is affected and list includes Solaris 10 and Solaris 11 Express. It is very easy to fall in this pitfall if you have some automated package installation which may invoke some scripts for starting applications at the end of installation while cleaning up the temporary directory the package was running from. I wasted couple of hours in going over all my scripts to understand what was going on. The ls command was working but find was not able to get me the list of files to process from unrelated directories. So I ended up redirecting find’s error out to standard out and viola, solution presents itself. That redirection should have been on top of my list. It tells you that “find : cannot get the current working directory”. Why it needs that? I don’t know. Linux has this fixed for some time now, but for some reason SunOS is still using the old find variant including Solaris 11 Express which is the latest version out. Maybe some historical reasons. If anyone know, please share.
So the solution to the problem was that before invoking the command that will continue to run and may need to call find, start it in a directory that will persist after package installation is complete, e.g. / or /tmp.
Lets see a working session.
unixite@sandboxS11:~> mkdir test unixite@sandboxS11:~> cd test unixite@sandboxS11:~/test> find /tmp -type f /tmp/.X0-lock /tmp/0_sun_studio/last_reg_try unixite@sandboxS11:~/test> su - unixite Password: Oracle Corporation SunOS 5.11 snv_151a November 2010 unixite@sandboxS11:~> rm -fr test unixite@sandboxS11:~> logout unixite@sandboxS11:~/test> find /tmp -type f ; echo $? find : cannot get the current working directory 1 unixite@sandboxS11:~/test> (cd /tmp; find /tmp -type f; echo $?) /tmp/.X0-lock /tmp/0_sun_studio/last_reg_try 0 unixite@sandboxS11:~/test>
Lets see what is going on under the covers while staying in the same setup.
unixite@sandboxS11:~/test> truss find /tmp -type f .... .... sysconfig(_CONFIG_PAGESIZE) = 4096 getcwd(0x0806A210, 1024) Err#2 ENOENT open("/usr/lib/locale/en_US.UTF-8/LC_MESSAGES/SUNW_OST_OSCMD.mo", O_RDONLY) Err#2 ENOENT fstat64(2, 0x08046AC0) = 0 findwrite(2, " f i n d", 4) = 4 : cannot get the current working directory write(2, " : c a n n o t g e".., 44) = 44 _exit(1) unixite@sandboxS11:~/test>
So it clearly indicates that it is checking for current working directory using getcwd and if fails to find it bails out. Strangely enough it is not affected by the permissions on that directory but it is affected by the directory’s existence. If the directory was on NFS drive you will get Error Code 151 or ESTALE (getcwd(0x0806A210, 1024) Err#151 ESTALE) again pointing that current working directory must exist.
Latest Linux Variants are not affected by this bug or feature of find. So exercise caution and use (cd /tmp; find) variance of the command when triggering from automated or batch jobs until all Unix variants start to use a version of find that does not need to look for current working directory before proceeding. At that point of time, this article will be outdated :-).