From 57c929da8bbc297249dadc560e8e3a569b0d685d Mon Sep 17 00:00:00 2001 From: Jérémy Compostella Date: Fri, 9 Mar 2012 19:21:42 +0100 Subject: dirname: support more than one argument * src/dirname.c (main): Handle new -z option and manage more than one argument. * doc/coreutils.texi (dirname invocation): Mention it. * NEWS (New features): Mention it. * tests/misc/dirname: Add a two arguments test. --- NEWS | 3 +++ doc/coreutils.texi | 26 +++++++++++++----- src/dirname.c | 77 +++++++++++++++++++++++++++++++++++------------------- tests/misc/dirname | 3 +-- 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 #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 = ˙ + len = 1; + } - if (! len) - { - result = ˙ - 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. -- cgit v1.2.3-54-g00ecf