Why is it that find prints out a leading ./ to results if no paths are given?
$ find
./file1
./file2
./file3
What is the reason for not printing out this?
$ find
file1
file2
file3
The reason why you see this is because the developer of GNU find chose to provide a "reasonable" behavior for find when no path is given. In contrast, POSIX doesn't state that the parameter is optional:
The
findutility shall recursively descend the directory hierarchy from each file specified by path, evaluating a Boolean expression composed of the primaries described in the OPERANDS section for each file encountered. Each path operand shall be evaluated unaltered as it was provided, including all trailing<slash>characters; all pathnames for other files encountered in the hierarchy shall consist of the concatenation of the current path operand, a<slash>if the current path operand did not end in one, and the filename relative to the path operand. The relative portion shall contain no dot or dot-dot components, no trailing characters, and only single<slash>characters between pathname components.
You can see the difference in the synopsis for each. GNU has (as is the convention) optional items in square brackets:
find [-H] [-L] [-P] [-D debugopts] [-Olevel] [starting-point...]
[expression]
while POSIX doesn't indicate that it can be optional:
find [-H|-L] path... [operand_expression...]
In the GNU program, that's done in ftsfind.c:
if (empty)
{
/*
* We use a temporary variable here because some actions modify
* the path temporarily. Hence if we use a string constant,
* we get a coredump. The best example of this is if we say
* "find -printf %H" (note, not "find . -printf %H").
*/
char defaultpath[2] = ".";
return find (defaultpath);
}
and a literal "." is used for simplicity. So you'll see the same result with
find
and
find .
because (and POSIX agrees) the given path will be used to prefix the results (see above for concatenation).
With a little work, one could determine when the feature was first added; it was present in the initial creation of "findutils" in 1996 (see find.c):
+ /* If no paths are given, default to ".". */
+ for (i = 1; i < argc && strchr ("-!(),", argv[i][0]) == NULL; i++)
+ process_top_path (argv[i]);
+ if (i == 1)
+ process_top_path (".");
+
+ exit (exit_status);
+}
From the changelog for find 3.8, this was apparently
Sat Dec 15 19:01:12 1990 David J. MacKenzie (djm at egypt)
* find.c (main), util.c (usage): Make directory args optional,
defaulting to "."
Usually, one does post-processing of the files and, in that case, there can be a huge advantage to starting the filename with ./. In particular, if a file name starts with -, a subsequent command could interpret that filename an option. ./ avoids that.
As an example, consider a directory with these files:
$ ls
--link --no-clobber
Now, imagine how this command would work if the file names were provided without the ./ in front:
$ find -type f -exec cp -t ../ {} +
We can illustrate the problem with find itself. Let's run it in the same directory as above. The following works:
$ find ./*
./--link
./--no-clobber
The following fails:
$ find *
find: unknown predicate `--link'
Try 'find --help' for more information.
The find command needs path(s) to search.
If we don't specify any,
it uses the current directory (.) as its starting point.
Similarly, if you pass the path, e.g., /tmp,
it considers that as its starting point.
And therefore the results.
If current directory:
$ find
or
$ find .
output:
./file1
./file2
./file3
If /tmp directory:
$ find /tmp
output:
/tmp/file4
/tmp/file5
If abc directory under the current directory:
$ find abc
output:
abc/file6
abc/file7
If multiple directories under the current directory:
$ find fu bar
output:
fu/file10
fu/file11
bar/file8
bar/file9
find needs a path to search anything and that it defaults to the current directory. The question is why it prints out the leading ./ when file.txt is just the same as ./file.txt.
– n.r.
Aug 05 '16 at 17:32
If you do not specify a path, find command assumes the ${PWD} as the path and prints it out on its output. User not specifying the path doesn't change the way find works. And find always works with paths by default.
/tmp, run the command find /tmp If you do not specify a path it will always be current directory, which is ./
– MelBurslan
Aug 05 '16 at 17:06
find ., find $PWD and find (without a path, if your find supports it).
– ilkkachu
Aug 05 '16 at 17:24
find *. – n.r. Aug 05 '16 at 17:10filedemand the user to give a path (like the BSD find on OS X). So you usually need to explicitly say something likefind . -type f .... From there, it's not a big step for some versions of find (like GNU find) to just default to.and leave everything else as is. – ilkkachu Aug 05 '16 at 17:23find *not showing the.is because*lists all files and folders, but excludes.. Doecho *in a directory that contains only one or two files, and you will see that.is not listed. Thus,find *operates on each file expanded. It's the same as if you saidfind Desktop/from home directory. You will see output asDesktop/foo_bar.txt– Sergiy Kolodyazhnyy Aug 06 '16 at 05:28find foodoesn't prepend./- it prependsfoo/– user253751 Aug 06 '16 at 08:52-filesfrom getting interpreted as flags tofinditself. – n.r. Aug 06 '16 at 13:32find *print. .. file1 file2 file3?”; it’s “Why doesn’tfind *print./file1 ./file2 ./file3?”. immibis (and Mrigesh and Thomas Dickey) have answered that question. – G-Man Says 'Reinstate Monica' Aug 06 '16 at 21:16findbehaves the way it does. Do you have any authoritative reference information to support the implied claim thatfindwas designed to behave in this way for this reason? – G-Man Says 'Reinstate Monica' Aug 06 '16 at 21:19findbut with the*. Do the thing withecho *and you'll see – Sergiy Kolodyazhnyy Aug 06 '16 at 21:20find *will print onlyfile1 file2 file3. It will not print. .. file1 file2 file3– Sergiy Kolodyazhnyy Aug 06 '16 at 21:30