coreutils
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

Re: basename BSD compatibility and filter mode


From: Pádraig Brady
Subject: Re: basename BSD compatibility and filter mode
Date: Wed, 07 Mar 2012 02:02:05 +0000
User-agent: Mozilla/5.0 (X11; Linux x86_64; rv:6.0) Gecko/20110816 Thunderbird/6.0

On 03/04/2012 07:09 PM, Jérémy Compostella wrote:
>> [...]
>> I just logged onto an OS X box there and you're right:
>>
>> $ printf "%s\n" 1/1 2/2 | xargs basename
>> 1
>>
>> $ printf "%s\n" 1/1 2/2 3/3| xargs basename
>> 1
>> 2
>> 3
>>
>> However I think it's dangerous to do that.
>> If I was writing a script I would probably test with
>> 1 or 3 or more arguments. But the script would then fail if
>> given 2 args based on transient conditions.
>> I would not emulate that "feature".
> I do agree it's dangerous. I removed this "feature".
> 
>>> [...]
>>> Eric Blake said:
>>>> It's been brought up before, and the consensus has always been that if
>>>> someone would write the patches, it would be worthwhile.  We do need
>>>> support for a -0 or some other way to do NUL-terminated filtering,
>>>> though.
>>> which conflict with the idea that this feature is not really worth. I'm
>>> a bit confused now ...
>>
>> Yes, I agreed with Eric that -0 was useful,
>> but on consideration if not processing stdin,
>> then I don't think it's of use.
> OK.
> 
> I attached the patch. Feel free to comment.

Thanks again for doing that.
I've made the following tweaks and will push early tomorrow.

cheers,
Pádraig.

diff --git a/NEWS b/NEWS
index 082c5ec..2289d53 100644
--- a/NEWS
+++ b/NEWS
@@ -16,7 +16,9 @@ GNU coreutils NEWS                                    -*- outl
   split now accepts the --additional-suffix option, to append an
   additional static suffix to output file names.

-  basename now supports the -a and -s BSD options.
+  basename now supports the -a and -s options, which allow
+  processing more than one argument at a time.  Also the complementary
+  -z option was added to delimit output items with the NUL character.

 ** Bug fixes

diff --git a/doc/coreutils.texi b/doc/coreutils.texi
index d513c25..1c50764 100644
--- a/doc/coreutils.texi
+++ b/doc/coreutils.texi
@@ -12422,7 +12422,7 @@ This section describes commands that manipulate file nam

 @example
 basename @var{name} [@var{suffix}]
-basename [@var{option}]... [@var{name}]...
+basename @var{option}... @var{name}...
 @end example

 If @var{suffix} is specified and is identical to the end of @var{name},
@@ -12455,15 +12455,14 @@ Options must precede operands.
 @itemx --multiple
 @opindex -a
 @opindex --multiple
-Treat every argument as a @var{name} as if @command{basename} were
-invoked with just one argument.
+Support more than one argument.  Treat every argument as a @var{name},
+with a @var{suffix} needing to be specified using the @option{-s} option.

 @item -s @var{suffix}
-@itemx --sufix=@var{suffix}
+@itemx --suffix=@var{suffix}
 @opindex -s
 @opindex --suffix
-Remove a trailing @var{suffix}. If @samp{-s} is specified,
-@command{basename} acts as if @samp{-a} was specified too.
+Remove a trailing @var{suffix}.  @option{-s} implies @option{-a}.

 @end table

diff --git a/src/basename.c b/src/basename.c
index a1d28da..158ac7b 100644
--- a/src/basename.c
+++ b/src/basename.c
@@ -32,6 +32,7 @@ static struct option const longopts[] =
 {
   {"multiple", no_argument, NULL, 'a'},
   {"suffix", required_argument, NULL, 's'},
+  {"zero", no_argument, NULL, 'z'},
   {GETOPT_HELP_OPTION_DECL},
   {GETOPT_VERSION_OPTION_DECL},
   {NULL, 0, NULL, 0}
@@ -46,7 +47,7 @@ usage (int status)
     {
       printf (_("\
 Usage: %s NAME [SUFFIX]\n\
-  or:  %s [OPTION]... [NAME]...\n\
+  or:  %s OPTION... NAME...\n\
 "),
               program_name, program_name);
       fputs (_("\
@@ -56,20 +57,19 @@ If specified, also remove a trailing SUFFIX.\n\
 "), stdout);

       fputs (_("\
-  -a, --multiple  treat every argument as a NAME as if basename were\n\
-                  invoked with just one argument.\n\
-  -s, --suffix=SUFFIX  remove a trailing SUFFIX.\n\
+  -a, --multiple       support multiple arguments and treat each as a NAME\n\
+  -s, --suffix=SUFFIX  remove a trailing SUFFIX\n\
+  -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/sort       Output \"sort\".\n\
-  %s include/stdio.h .h  Output \"stdio\".\n\
-  %s -s .h include/stdio.h  Output \"stdio\".\n\
-  %s -a -s .h include/stdio.h include/stdlib.h  Output \"stdio\" followed by\
- \"stdlib\".\n\
+  %s /usr/bin/sort          -> \"sort\"\n\
+  %s include/stdio.h .h     -> \"stdio\"\n\
+  %s -s .h include/stdio.h  -> \"stdio\"\n\
+  %s -a any/str1 any/str2   -> \"str1\" followed by \"str2\"\n\
 "),
               program_name, program_name, program_name, program_name);
       emit_ancillary_info ();
@@ -97,10 +97,10 @@ remove_suffix (char *name, const char *suffix)
 }

 /* Perform the basename operation on STRING.  If SUFFIX is non-NULL, remove
-   the trailing suffix SUFFIX. Finally, output the result string.  */
+   the trailing SUFFIX.  Finally, output the result string.  */

 static void
-perform_basename (const char *string, const char *suffix)
+perform_basename (const char *string, const char *suffix, bool use_nuls)
 {
   char *name = base_name (string);
   strip_trailing_slashes (name);
@@ -114,14 +114,16 @@ perform_basename (const char *string, const char *suffix)
   if (suffix && IS_RELATIVE_FILE_NAME (name) && ! FILE_SYSTEM_PREFIX_LEN (name)
     remove_suffix (name, suffix);

-  puts (name);
+  fputs (name, stdout);
+  putchar (use_nuls ? '\0' : '\n');
   free (name);
 }

 int
 main (int argc, char **argv)
 {
-  unsigned char multiple_names = 0;
+  bool multiple_names = false;
+  bool use_nuls = false;
   const char *suffix = NULL;

   initialize_main (&argc, &argv);
@@ -134,7 +136,7 @@ main (int argc, char **argv)

   while (true)
     {
-      int c = getopt_long (argc, argv, "as:", longopts, NULL);
+      int c = getopt_long (argc, argv, "as:z", longopts, NULL);

       if (c == -1)
         break;
@@ -145,7 +147,11 @@ main (int argc, char **argv)
           suffix = optarg;

         case 'a':
-          multiple_names = 1;
+          multiple_names = true;
+          break;
+
+        case 'z':
+          use_nuls = true;
           break;

         case_GETOPT_HELP_CHAR;
@@ -169,11 +175,13 @@ main (int argc, char **argv)
     }

   if (multiple_names)
-    for (; optind < argc; optind++)
-      perform_basename (argv[optind], suffix);
+    {
+      for (; optind < argc; optind++)
+        perform_basename (argv[optind], suffix, use_nuls);
+    }
   else
     perform_basename (argv[optind],
-                      optind + 2 == argc ? argv[optind + 1] : NULL);
+                      optind + 2 == argc ? argv[optind + 1] : NULL, use_nuls);

   exit (EXIT_SUCCESS);
 }



reply via email to

[Prev in Thread] Current Thread [Next in Thread]