[linux] Extract file basename without path and extension in bash

Pure bash, no basename, no variable juggling. Set a string and echo:

p=/the/path/foo.txt
echo "${p//+(*\/|.*)}"

Output:

foo

Note: the bash extglob option must be "on", (Ubuntu sets extglob "on" by default), if it's not, do:

shopt -s extglob

Walking through the ${p//+(*\/|.*)}:

  1. ${p -- start with $p.
  2. // substitute every instance of the pattern that follows.
  3. +( match one or more of the pattern list in parenthesis, (i.e. until item #7 below).
  4. 1st pattern: *\/ matches anything before a literal "/" char.
  5. pattern separator | which in this instance acts like a logical OR.
  6. 2nd pattern: .* matches anything after a literal "." -- that is, in bash the "." is just a period char, and not a regex dot.
  7. ) end pattern list.
  8. } end parameter expansion. With a string substitution, there's usually another / there, followed by a replacement string. But since there's no / there, the matched patterns are substituted with nothing; this deletes the matches.

Relevant man bash background:

  1. pattern substitution:
  ${parameter/pattern/string}
          Pattern substitution.  The pattern is expanded to produce a pat
          tern just as in pathname expansion.  Parameter is  expanded  and
          the  longest match of pattern against its value is replaced with
          string.  If pattern begins with /, all matches  of  pattern  are
          replaced   with  string.   Normally  only  the  first  match  is
          replaced.  If pattern begins with #, it must match at the begin-
          ning of the expanded value of parameter.  If pattern begins with
          %, it must match at the end of the expanded value of  parameter.
          If string is null, matches of pattern are deleted and the / fol
          lowing pattern may be omitted.  If parameter is @ or *, the sub
          stitution  operation  is applied to each positional parameter in
          turn, and the expansion is the resultant list.  If parameter  is
          an  array  variable  subscripted  with  @ or *, the substitution
          operation is applied to each member of the array  in  turn,  and
          the expansion is the resultant list.
  1. extended pattern matching:
  If the extglob shell option is enabled using the shopt builtin, several
   extended  pattern  matching operators are recognized.  In the following
   description, a pattern-list is a list of one or more patterns separated
   by a |.  Composite patterns may be formed using one or more of the fol
   lowing sub-patterns:

          ?(pattern-list)
                 Matches zero or one occurrence of the given patterns
          *(pattern-list)
                 Matches zero or more occurrences of the given patterns
          +(pattern-list)
                 Matches one or more occurrences of the given patterns
          @(pattern-list)
                 Matches one of the given patterns
          !(pattern-list)
                 Matches anything except one of the given patterns

Examples related to linux

grep's at sign caught as whitespace How to prevent Google Colab from disconnecting? "E: Unable to locate package python-pip" on Ubuntu 18.04 How to upgrade Python version to 3.7? Install Qt on Ubuntu Get first line of a shell command's output Cannot connect to the Docker daemon at unix:/var/run/docker.sock. Is the docker daemon running? Run bash command on jenkins pipeline How to uninstall an older PHP version from centOS7 How to update-alternatives to Python 3 without breaking apt?

Examples related to bash

Comparing a variable with a string python not working when redirecting from bash script Zipping a file in bash fails How do I prevent Conda from activating the base environment by default? Get first line of a shell command's output Fixing a systemd service 203/EXEC failure (no such file or directory) /bin/sh: apt-get: not found VSCode Change Default Terminal Run bash command on jenkins pipeline How to check if the docker engine and a docker container are running? How to switch Python versions in Terminal?

Examples related to unix

Docker CE on RHEL - Requires: container-selinux >= 2.9 What does `set -x` do? How to find files modified in last x minutes (find -mmin does not work as expected) sudo: npm: command not found How to sort a file in-place How to read a .properties file which contains keys that have a period character using Shell script gpg decryption fails with no secret key error Loop through a comma-separated shell variable Best way to find os name and version in Unix/Linux platform Resource u'tokenizers/punkt/english.pickle' not found

Examples related to filenames

Rename multiple files in a folder, add a prefix (Windows) How to loop over files in directory and change path and add suffix to filename Why do I get a SyntaxError for a Unicode escape in my file path? Git copy file preserving history A html space is showing as %2520 instead of %20 How do I get the file name from a String containing the Absolute file path? DateTime.ToString() format that can be used in a filename or extension? Get only filename from url in php without any variable values which exist in the url Obtaining only the filename when using OpenFileDialog property "FileName" Build the full path filename in Python