Tom's Guide | Tom's Hardware | Tom's Games
![]() |
![]() |
![]() |
Where I'm working they have a script that uses e.g:
find $SOMEPATH/*.dat -mtime +42 -print
In all the documentation I've read, the first argument should be a search path and filenames should be specified with -name 'pattern'. I said it was wrong and wouldn't work, but it turns out it does (HP-UX) so I look like an idiot. I then tried it at home on my Mac and it works there too (FreeBSD). Am I missing something?

The first argument is actually pathname_list which can be multiple pathnames, such as:
find /tmp /u01/home ...
I think a lot of people (including me) think of pathname as only a directory. But in fact, it is a full-path reference to EITHER a directory or a file. Therefore, pathname_list can be directories, files, or a mixture of files and directories.
And of course, the shell is expanding that fileset before the find command ever sees it. So,
find myfile* -print
actually gets processed as:
find myfile1 myfile2 myfile3 -print
That fileset expansion could get very long and exceed a shell processing limit. If that happens, you can tell them they need to change it to:
find directory-list -name "*.dat" -mtime +42 -print
because the "*.dat" will not be expanded by the shell, but instead passed to the find command as is, where it will be used by find as a pattern match.
and THEN you will get the respect you deserve! :-))

Did you find 'pathname' defined anywhere? The man pages are a bit light on exactly what that means.
If I have files xx, yy and zz (and assuming no subdirectories):
find . -name '??' -print
# gives xx, yy, zz as expectedfind ??
# expands to 'find xx yy zz'
# returns xx, yy, zz as we now know to expectfind aa
# fails with error 'find: cannot stat aa'. When I tested
# the original script I got this error, which led me to
# think the syntax was invalid.find '??'
# fails as above because there is no file named literally ??find xx -name yy
# can never succeed - unless xx is a directory
# and yy exists somewhere under it...A few years ago I was working somewhere with a particularly useless DBA who would enter commands like
find . -name *.sql -print
No matter how many times we explained it to him he never understood why that sometimes worked (no files matching '*.sql' in the directory he was in), sometimes gave 'missing conjunction' (more than one file, thus giving a syntax error when expanded) and sometimes failed to find a file that was actually there (one file matching '*.sql' in current directory - took some thinking about at first).

Yep, very good. I don't have a formal definition of pathname. I would say it is any full reference (root-anchored) name for any type of file or directory.
Just curious - why would find command fail to find a single *.sql file?

$ mkdir testdir
$ touch testdir/aa.dat testdir/bb.dat testdir/cc.dat
$ find testdir -name a*.dat -print
# Shell can't expand a*.dat, so find goes looking
# for a*.dat
# and finds one matching file:testdir/aa.dat
$ touch az.dat
# Repeat same find command:
$ find testdir -name a*.dat -print# a*.dat expands to 'az.dat': find goes looking for az.dat
# and finds nothing.Also on the subject of this new (to me) syntax:
$ find aa.dat
# Not equivalent to "find . -name aa.dat":
# finds nothing.

Yes, good examples. It is not the fault of the find command that:
find testdir -name a*.dat -print
does not find anything in the testdir subdirectory when a*.dat is expanded to az.dat.
The shell has been given, by default, permission to expand those patterns. Thus, as you point out, the shell changes it to
find testdir -name az.dat -print
before the find command ever executes. And as you pointed out earlier, if a*.dat were to expand into multiple filenames, this would result in "find: missing conjunction".
While it is valid syntax for pathname_list to expand into multiple entries, it is not valid for a -name pattern to do so. Therefore, the user needs to either protect these patterns from expanding by enclosing in double-quotes, or tell the shell not to do filename expansion.
The shell can be invoked with the -f option
sh -f
or by dynamically changing the noglob option. To see current shell options:
echo $-
Turn off noglob:
set -f
echo $-Now, the command
find testdir -name a*.dat -print
will find testdir/aa.dat because a*.dat was not expanded into az.dat.
And regarding your last paragraph:
find aa.dat
finds nothing because the only pathname it was told to look at was aa.dat. It does not see aa.dat, so it finds nothing. The find command searches only the pathnames listed. It will not automatically process all files and directories in the current directory.
find testdir
will process that one pathname only. If it is a file, then it "finds" that one file. If it is a directory, it finds all files lying on that path.
find . -name aa.dat
Above command specifies the current directory as the pathname to process, so it processes all files and directories in the directory, so it will find any aa.dat files in the current directory or in any subdirectories.

Yes, quite agree about shell wildcard expansion not being find's problem. I would always put wildcard expressions within a -name pattern in quotes. Just thought it made an interesting illustration of some of the perils.
I still think it's not immediately obvious from the documentation that
find aa.dat
is equivalent to something like
find . -path ./aa.dat
(except that an invalid path is an error condition, while no files found is not). I suppose it does make some sort of sense once you know.

![]() |
![]() |
![]() |

This post is quite old and has been locked from receiving new replies. Please create a new posting instead.
| Ads by Google |