summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--NEWS3
-rw-r--r--doc/coreutils.texi26
-rw-r--r--src/dirname.c77
-rwxr-xr-xtests/misc/dirname3
4 files changed, 73 insertions, 36 deletions
diff --git a/NEWS b/NEWS
index 87ef7bd94..f783afb15 100644
--- a/NEWS
+++ b/NEWS
@@ -35,6 +35,9 @@ GNU coreutils NEWS -*- outline -*-
of more than one argument at a time. Also the complementary
-z option was added to delimit output items with the NUL character.
+ dirname now supports more than one argument. Also the complementary
+ -z option was added to delimit output items with the NUL character.
+
** Bug fixes
du --one-file-system (-x) would ignore any non-directory specified on
diff --git a/doc/coreutils.texi b/doc/coreutils.texi
index f9207e773..39c9bbf67 100644
--- a/doc/coreutils.texi
+++ b/doc/coreutils.texi
@@ -12514,13 +12514,13 @@ basename -a -s .h include/stdio.h include/stdlib.h
@cindex stripping non-directory suffix
@cindex non-directory suffix, stripping
-@command{dirname} prints all but the final slash-delimited component of
-@var{name}. Slashes on either side of the final component are also
-removed. If the string contains no slash, @command{dirname} prints
-@samp{.} (meaning the current directory). Synopsis:
+@command{dirname} prints all but the final slash-delimited component
+of each @var{name}. Slashes on either side of the final component are
+also removed. If the string contains no slash, @command{dirname}
+prints @samp{.} (meaning the current directory). Synopsis:
@example
-dirname @var{name}
+dirname [@var{option}] @var{name}...
@end example
@var{name} need not be a file name, but if it is, this operation
@@ -12534,8 +12534,17 @@ including the case when the final component is itself a directory.
result is @samp{//} on platforms where @var{//} is distinct from
@var{/}, and @samp{/} on platforms where there is no difference.
-The only options are @option{--help} and @option{--version}. @xref{Common
-options}.
+The program accepts the following option. Also see @ref{Common options}.
+
+@table @samp
+
+@item -z
+@itemx --zero
+@opindex -z
+@opindex --zero
+Separate output items with @sc{nul} characters.
+
+@end table
@exitstatus
@@ -12546,6 +12555,9 @@ Examples:
dirname /usr/bin/sort
dirname /usr/bin//.//
+# Output "dir1" followed by "dir2"
+dirname dir1/str dir2/str
+
# Output ".".
dirname stdio.h
@end smallexample
diff --git a/src/dirname.c b/src/dirname.c
index 3637a046f..ac218d5d9 100644
--- a/src/dirname.c
+++ b/src/dirname.c
@@ -23,9 +23,7 @@
#include <sys/types.h>
#include "system.h"
-#include "long-options.h"
#include "error.h"
-#include "quote.h"
/* The official name of this program (e.g., no 'g' prefix). */
#define PROGRAM_NAME "dirname"
@@ -34,6 +32,14 @@
proper_name ("David MacKenzie"), \
proper_name ("Jim Meyering")
+static struct option const longopts[] =
+{
+ {"zero", no_argument, NULL, 'z'},
+ {GETOPT_HELP_OPTION_DECL},
+ {GETOPT_VERSION_OPTION_DECL},
+ {NULL, 0, NULL, 0}
+};
+
void
usage (int status)
{
@@ -42,24 +48,27 @@ usage (int status)
else
{
printf (_("\
-Usage: %s NAME\n\
- or: %s OPTION\n\
+Usage: %s [OPTION] NAME...\n\
"),
- program_name, program_name);
+ program_name);
fputs (_("\
-Output NAME with its last non-slash component and trailing slashes removed;\n\
-if NAME contains no /'s, output '.' (meaning the current directory).\n\
+Output each NAME with its last non-slash component and trailing slashes\n\
+removed; if NAME contains no /'s, output '.' (meaning the current directory).\n\
\n\
"), stdout);
+ fputs (_("\
+ -z, --zero separate output with NUL rather than newline\n\
+"), stdout);
fputs (HELP_OPTION_DESCRIPTION, stdout);
fputs (VERSION_OPTION_DESCRIPTION, stdout);
printf (_("\
\n\
Examples:\n\
- %s /usr/bin/ Output \"/usr\".\n\
- %s stdio.h Output \".\".\n\
+ %s /usr/bin/ -> \"/usr\"\n\
+ %s dir1/str dir2/str -> \"dir1\" followed by \"dir2\"\n\
+ %s stdio.h -> \".\"\n\
"),
- program_name, program_name);
+ program_name, program_name, program_name);
emit_ancillary_info ();
}
exit (status);
@@ -69,6 +78,7 @@ int
main (int argc, char **argv)
{
static char const dot = '.';
+ bool use_nuls = false;
char const *result;
size_t len;
@@ -80,10 +90,26 @@ main (int argc, char **argv)
atexit (close_stdout);
- parse_long_options (argc, argv, PROGRAM_NAME, PACKAGE_NAME, Version,
- usage, AUTHORS, (char const *) NULL);
- if (getopt_long (argc, argv, "+", NULL, NULL) != -1)
- usage (EXIT_FAILURE);
+ while (true)
+ {
+ int c = getopt_long (argc, argv, "z", longopts, NULL);
+
+ if (c == -1)
+ break;
+
+ switch (c)
+ {
+ case 'z':
+ use_nuls = true;
+ break;
+
+ case_GETOPT_HELP_CHAR;
+ case_GETOPT_VERSION_CHAR (PROGRAM_NAME, AUTHORS);
+
+ default:
+ usage (EXIT_FAILURE);
+ }
+ }
if (argc < optind + 1)
{
@@ -91,23 +117,20 @@ main (int argc, char **argv)
usage (EXIT_FAILURE);
}
- if (optind + 1 < argc)
+ for (; optind < argc; optind++)
{
- error (0, 0, _("extra operand %s"), quote (argv[optind + 1]));
- usage (EXIT_FAILURE);
- }
+ result = argv[optind];
+ len = dir_len (result);
- result = argv[optind];
- len = dir_len (result);
+ if (! len)
+ {
+ result = &dot;
+ len = 1;
+ }
- if (! len)
- {
- result = &dot;
- len = 1;
+ fwrite (result, 1, len, stdout);
+ putchar (use_nuls ? '\0' :'\n');
}
- fwrite (result, 1, len, stdout);
- putchar ('\n');
-
exit (EXIT_SUCCESS);
}
diff --git a/tests/misc/dirname b/tests/misc/dirname
index 37cf7cf18..002183678 100755
--- a/tests/misc/dirname
+++ b/tests/misc/dirname
@@ -35,8 +35,6 @@ my @Tests =
(
['fail-1', {ERR => "$prog: missing operand\n"
. "Try '$prog --help' for more information.\n"}, {EXIT => '1'}],
- ['fail-2', qw(a b), {ERR => "$prog: extra operand 'b'\n"
- . "Try '$prog --help' for more information.\n"}, {EXIT => '1'}],
['a', qw(d/f), {OUT => 'd'}],
['b', qw(/d/f), {OUT => '/d'}],
@@ -51,6 +49,7 @@ my @Tests =
['k', qw(///a///b), {OUT => '///a'}],
['l', qw(///a//b/), {OUT => '///a'}],
['m', qw(''), {OUT => '.'}],
+ ['n', qw(a/b c/d), {OUT => "a\nc"}],
);
# Append a newline to end of each expected 'OUT' string.