This behaviour comes from find
, and is specified by POSIX:
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 default action, -print
, outputs the full pathname to standard out.
find
outputs the paths of files it finds starting from the path(s) given on its command line.
find .
asks find
to look for files under .
and its subdirectories, and it presents the results starting with ./
;
find foo
would do the same but starting with foo
, and it would produce results starting with foo/
.
I don’t think find
does this specifically to prevent problems with un-prefixed file names; rather, it does this for consistency — regardless of the path provided as argument, the output of -print
always starts with that path.
With the GNU implementation of find
, you can strip the initial path off the start of the printed file by using -printf '%P\n'
in place of -print
. For instance with find foo/bar -name file -printf '%P\n'
or find . -name file -printf '%P\n'
, you'd get dir/file
instead of foo/bar/dir/file
or ./dir/file
for those files.
More generally, having ./
as a prefix can help prevent errors, e.g. if you have files with names starting with dashes; for example if you have a file named -f
, rm -f
won’t delete it, but rm ./-f
will.
When running commands with a shell or with exec*p()
standard C functions (and their equivalent in other languages), when the command name doesn't contain a /
, the path of command is looked in $PATH
instead of being interpreted as a relative path (the file in the current working directory). Same applies for the argument to the .
/ source
special builtins of several shells (including POSIX compliant sh
implementations). Using ./cmd
in that case instead of cmd
, which is another way to specify the same relative path, but with a /
in it is how you typically invoke a command stored in the current working directory.
find
, libc has nothing to with that. – Artem S. Tashkinov Aug 09 '22 at 08:15-exec
andxargs
. The latter shows the problem with-print
. If you use-exec
, you don’t needxargs
; if you’re usingxargs
, you’d end up withfind -printf '%P\0' | xargs -0 rm
which would break. (It’s trivially fixable withrm --
on systems whererm
recognises--
, but hopefully it still demonstrates the issue.) – Stephen Kitt Aug 09 '22 at 11:41.deb
with apt. Exampleapt install discord
installs from sources, andapt install ./discord
installs local file called "discord" in the current dir – Brian Leishman Aug 09 '22 at 19:55./something
is less confusing thansomething
. The latter does not have to be a path, but the former almost certainly is. – Kamil Maciorowski Aug 09 '22 at 21:09-print
could be the input to anything.find
doesn't make assumptions. – hobbs Aug 10 '22 at 01:04find . .. -prune
prints.
and..
,find . .. -maxdepth 1
prints. ./file1... .. ../file2
... Would you like it to special-case.
and remove the./
prefixes, for cosmetic purposes at the expense of safety and portability? – Stéphane Chazelas Aug 12 '22 at 08:08