bashrhelbasename

basename throws error when a wildcard is specified


I want to get the filename from a file path. It works fine when one file is specified, such as:

fname=$(basename -- /tmp/file1)

However, if provided as an expression such as fname=$(basename -- /tmp/fi*) it throws basename: extra operand ‘/tmp/file1’.

In above case I don't expect it to resolve and expand the expression but rather just return fi* in fname, is it possible to do it using basename?


Solution

  • As stated in comments; the basename command only provides base name for an individual file. If you need to collect base name from multiple files matching a wildcard * pattern, then you need to either work with arrays, or iterate the globbing pattern matches:

    With Bash arrays:

    #!/usr/bin/env bash
    
    # Populates the files array with the wildcard pattern glob expansion
    files=(/tmp/fi*)
    
    # Strip each individual file names starting with anything and up to last /
    # stores the results into another basenames array
    basenames=("${files[@]##*/}")
    
    # Iterate the basenames array to work with
    for abasename in "${basenames[@]}"; do
      : do something with each "$abasename"
    done
    

    Now if the shell you use has no support for arrays, you may iterate directly and process base names one by one:

    #!/bin/sh
    
    for afile in /tmp/fi*; do
    
      # strip the directory path to get basename
      abasename="${afile##*/}"
    
      : do something with that "$abasename"
    done