summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorBernhard Voelker <mail@bernhard-voelker.de>2022-03-29 00:24:47 +0200
committerBernhard Voelker <mail@bernhard-voelker.de>2022-04-24 13:35:49 +0200
commit6d2fa2c9a065743b9655427cedaf54bb55cd143f (patch)
tree9868863a80f7bb06ddcc5795c268abe9b5a9dd36
parent82e81acc5cf0caaf493227ad80bf35e85089eb48 (diff)
downloadfindutils-6d2fa2c9a065743b9655427cedaf54bb55cd143f.tar.gz
find: omit warning diagnostic for -name '/'
Although usually a pattern containing a directory separator does not match anything, a pattern solely consisting of one '/' still does (and has to) for the root directory "/". * find/parser.c (check_name_arg): Omit the warning in the case the given pattern equals "/". find/find.1 (-name): Clarify better that the pattern "/" is valid to match the "/" directory. * init.cfg (find_emits_warnings_): Add utility function. * tests/find/name-slash.sh: Add test. * tests/local.mk (all_tests): Reference it. * MEWS (Bug Fixes): Mention the fix. Fixes https://savannah.gnu.org/bugs/?62227
-rw-r--r--NEWS6
-rw-r--r--find/find.125
-rw-r--r--find/parser.c14
-rw-r--r--init.cfg9
-rwxr-xr-xtests/find/name-slash.sh68
-rw-r--r--tests/local.mk1
6 files changed, 105 insertions, 18 deletions
diff --git a/NEWS b/NEWS
index b9e28fb9..6b8c3493 100644
--- a/NEWS
+++ b/NEWS
@@ -2,6 +2,12 @@ GNU findutils NEWS - User visible changes. -*- outline -*- (allout)
* Noteworthy changes in release ?.? (????-??-??) [?]
+** Bug Fixes
+
+ 'find -name /' no longer outputs a warning, because that is a valid pattern
+ to match the root directory "/". Previously, a diagnostic falsely claimed
+ that this pattern would not match anything. [#62227]
+
* Noteworthy changes in release 4.9.0 (2022-02-22) [stable]
diff --git a/find/find.1 b/find/find.1
index 6bad0096..b3ec9753 100644
--- a/find/find.1
+++ b/find/find.1
@@ -848,20 +848,23 @@ modification times.
Base of file name (the path with the leading directories removed)
matches shell pattern
.IR pattern .
-Because the leading directories are removed,
-the file names considered for a match with
-.B \-name
-will never include a slash, so `\-name a/b' will never match anything
-(you probably need to use
+Because the leading directories of the file names are removed, the
+.I pattern
+should not include a slash, because `\-name a/b' will never match anything
+(and you probably want to use
.B \-path
instead).
-A warning is issued if you try to do this,
-unless the environment variable
+An exception to this is when using only a slash as \fIpattern\fR (`-name /'),
+because that is a valid string for matching the root directory "/" (because the
+base name of "/" is "/").
+A warning is issued if you try to pass a pattern containing a - but not
+consisting solely of one - slash, unless the environment variable
.B POSIXLY_CORRECT
-is set.
-The metacharacters (`*', `?',
-and `[]') match a `.\&' at the start of the base name (this is a change
-in findutils-4.2.2; see section STANDARDS CONFORMANCE below). To ignore a
+is set or the option
+.B \-nowarn
+is used.
+
+To ignore a
directory and the files under it, use
.B \-prune
rather than checking every file in the tree;
diff --git a/find/parser.c b/find/parser.c
index 75c730c3..5774bd94 100644
--- a/find/parser.c
+++ b/find/parser.c
@@ -1270,16 +1270,16 @@ fnmatch_sanitycheck (void)
static void
check_name_arg (const char *pred, const char *alt, const char *arg)
{
- if (should_issue_warnings () && strchr (arg, '/'))
+ if (should_issue_warnings () && strchr (arg, '/') && (0 != strcmp ("/", arg)))
{
error (0, 0,
_("warning: %s matches against basenames only, "
- "but the given pattern contains a directory separator (%s), "
- "thus the expression will evaluate to false all the time. "
- "Did you mean %s?"),
- safely_quote_err_filename (0, pred),
- safely_quote_err_filename (1, "/"),
- safely_quote_err_filename (2, alt));
+ "but the given pattern contains a directory separator (%s), "
+ "thus the expression will evaluate to false all the time. "
+ "Did you mean %s?"),
+ safely_quote_err_filename (0, pred),
+ safely_quote_err_filename (1, "/"),
+ safely_quote_err_filename (2, alt));
}
}
diff --git a/init.cfg b/init.cfg
index 5e422291..98423613 100644
--- a/init.cfg
+++ b/init.cfg
@@ -514,6 +514,15 @@ fiemap_capable_()
python "$abs_srcdir"/tests/fiemap-capable "$@"
}
+# Determine if find(1) emits warnings. This is not the case
+# e.g. if stdin is not a tty.
+find_emits_warnings_()
+{
+ # Find usually emits a warning for the deprecated -d option.
+ find -maxdepth 0 -d -quit 2>&1 \
+ | grep -q 'warning:'
+}
+
# Skip the current test if "." lacks d_type support.
require_dirent_d_type_()
{
diff --git a/tests/find/name-slash.sh b/tests/find/name-slash.sh
new file mode 100755
index 00000000..abd9522e
--- /dev/null
+++ b/tests/find/name-slash.sh
@@ -0,0 +1,68 @@
+#!/bin/sh
+# Exercise 'find -name PATTERN' behavior with a '/' in PATTERN.
+
+# Copyright (C) 2022 Free Software Foundation, Inc.
+
+# This program is free software: you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation, either version 3 of the License, or
+# (at your option) any later version.
+
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+
+# You should have received a copy of the GNU General Public License
+# along with this program. If not, see <https://www.gnu.org/licenses/>.
+
+. "${srcdir=.}/tests/init.sh"; fu_path_prepend_
+print_ver_ find
+
+# Ensure that find does not generally skip warnings due to POSIX requirements.
+unset POSIXLY_CORRECT
+
+# Detect if find emits warnings.
+find_emits_warnings_ \
+ && fwarns=1 \
+ || fwarns=0
+
+# Exercise '-name PATTERN' with a '/' somewhere in PATTERN.
+find -name 'dir/file' > out 2> err || fail=1
+compare /dev/null out || fail=1
+if [ $fwarns = 1 ]; then
+ grep 'warning: .*matches against basenames only.* evaluate to false' err \
+ || { cat err; fail=1; }
+else
+ compare /dev/null out
+fi
+
+# Likewise in POSIX environment.
+POSIXLY_CORRECT=1 find -name 'dir/file' > out 2> err || fail=1
+compare /dev/null out || fail=1
+compare /dev/null err || fail=1
+
+# Likewise with -nowarn.
+find -nowarn -name 'dir/file' > out 2> err || fail=1
+compare /dev/null out || fail=1
+compare /dev/null err || fail=1
+
+# Exercise '-name /', i.e., PATTERN just being "/": no warning because this
+# is a valid basename in the (trivial) case comparing to root directory "/".
+echo '/' > exp || framework_failure_
+find / -maxdepth 0 -name '/' > out 2> err || fail=1
+compare exp out || fail=1
+compare /dev/null err || fail=1
+
+# Exercise '-name /' in POSIX environment.
+POSIXLY_CORRECT=1 find / -maxdepth 0 -name '/' > out 2> err || fail=1
+compare exp out || fail=1
+compare /dev/null err || fail=1
+
+# Exercise '-name /' with the -warn option.
+find / -warn -maxdepth 0 -name '/' > out 2> err || fail=1
+compare exp out || fail=1
+compare /dev/null err || fail=1
+
+
+Exit $fail
diff --git a/tests/local.mk b/tests/local.mk
index e75a9130..4e8efd41 100644
--- a/tests/local.mk
+++ b/tests/local.mk
@@ -110,6 +110,7 @@ all_tests = \
tests/find/inode-zero.sh \
tests/find/many-dir-entries-vs-OOM.sh \
tests/find/name-lbracket-literal.sh \
+ tests/find/name-slash.sh \
tests/find/printf_escapechars.sh \
tests/find/printf_escape_c.sh \
tests/find/printf_inode.sh \