0

I try to execute basename via find like this:

find ./test_folder -type f -exec basename {} +

But I get the following error:

basename: extra operand './test_folder/test/file.crt'

Why I get this though?

1 Answer 1

4

POSIX basename only supports this:

basename string [suffix]

What happens when providing more than two strings¹ is not specified by POSIX but in most if not all implementations results in a syntax error such as the extra operand one you're getting.

But even two strings are too many in your case because the second one would be interpreted as a suffix to remove. You don't want to specify suffix, so with POSIX basename you are limited to this:

basename string

i.e. to one string per invocation of basename. The syntax to invoke a separate basename for each pathname from find is:

find … -exec basename {} \;

(read Understanding the -exec option of find to get the difference between ; and +).

The GNU, ast-open, toybox and FreeBSD implementations of basename at least support -a (aliased to --multiple in GNU basename and --all in ast-open's) that allows them to work with -exec … + of find. With this option no operand is interpreted as a suffix to remove (use -s … if you need to remove suffixes). Example:

find … -exec basename -a {} +

But if you're on a GNU system, your find already has the capability to print the basename (tail) of the found files (and has had it decades before GNU basename added -a/--multiple) via its -printf predicate:

find … -printf '%f\n'

In zsh recursive globbing, you can use the :t modifier (from csh's history and parameter expansion from the late 70s) in a glob qualifier to get the tail of those paths:

print -rC1 -- test_folder/**/*(ND.:t)

(with also Nullglob, Dotglob qualifiers and . as the equivalent of find's -type f).


¹ Strictly speaking, like most utilities, it also accepts -- to signify the end of options, even if there's no option that POSIX specifies for basename. You use it for basename -- -file-.jpg .jpg or in basename -- "$file" when you can't guarantee $file won't start with -.

3
  • ... and with GNU find, -printf can be used to get the same result without using basename at all. Commented Nov 6, 2023 at 20:02
  • GNU find could provide the basename of the file without running an external command, -printf "%f\n". From the man: Print the basename; the file's name with any leading directories removed (only the last element).
    – aviro
    Commented Nov 6, 2023 at 20:02
  • The answer is now community wiki. Improve it at will. Commented Nov 6, 2023 at 20:05

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .