Subject: bug#24011: parallel find error

From: Assaf Gordon <[email-masked]>
Date: Sat, 16 Jul 2016 19:55:03 -0400

tag 24011 notabug
close 24011
stop

Hello,

> On Jul 16, 2016, at 15:42, jklowden <[email-masked]> wrote:
> 
> There appears to be an error in the parallel execution of find.  I
> created a minimal example below.
> 
> [...]
> 
> $ find .. -type f -name lx[tr]\*.1 -exec basename {} +
> basename: extra operand ‘../appl/fsgmatch/lxtransduce.1’
> Try 'basename --help' for more information.

There are several issues here, though none of them are bugs.

First,
The difference between "find -exec basename {} \;" and "find -exec basename {} +" :
The former will execute the program 'basename' once per file,
and the latter will execute it fewer times with multiple files as parameters.

The following will demonstrate:

   $ mkdir c
   $ touch c/1 c/2 c/3 c/4
   $ find c -type f
   c/1
   c/2
   c/3
   c/4

Compare:

   $ find c -type f -exec echo basename {} \;
   basename c/1
   basename c/2
   basename c/3
   basename c/4

   $ find c -type f -exec echo basename {} +
   basename c/1 c/2 c/3 c/4

Second,
the "basename" command by default accepts a single parameter (pathname) or two parameters (pathname and optional extension).
Running it with three or more parameters will cause the error you were experiencing:

  $ basename c/a.txt 
  a.txt

  $ basename c/a.txt .txt
  a

  $ basename c/a.txt .txt c
  basename: extra operand ‘c’
  Try 'basename --help' for more information.

That explains your error: using the "+" syntax, "find" executed 'basename' with multiple filenames, and basename rejected it as invalid syntax.

However,
basename from coreutils version 8.16 and newer (released in 2012) supports the "-a" option (gnu extension) that handles multiple filenames on the same command line.
Compare:

   $ basename c/a.txt c/b.txt c/c.txt
   basename: extra operand ‘c/c.txt’
   Try 'basename --help' for more information.

   $ basename -a c/a.txt c/b.txt c/c.txt
   a.txt
   b.txt
   c.txt

Continuing the example above, the following syntax should work and do what you wanted:

   $ find c -type f -exec basename -a {} +
   1
   2
   3
   4

As such, I'm closing this bug, but discussion can continue by replying to this thread.

regards,
- assaf