I am presently writing a Bash function to convert all the man pages listed by equery files <PACKAGE> | grep /usr/share/man/man (if you are unfamiliar equery is a tool used on Gentoo-based systems that is from the app-portage/gentoolkit package) into HTML files and one bit of information I need in order to do this is how I can remove everything but the man page's name, without its file extension, from its full path. I realize this phrasing may be confusing so I will explain what I mean by this with an example. Running equery files sys-apps/portage | grep /usr/share/man/man gives the output:


out of this output say I take the final line /usr/share/man/man5/xpak.5.bz2 (which in the wording I used previously is this man page's full path), for the purpose of my example. Then what I would want to extract from it, within a Bash script, is xpak.5 (which is its file name, without its extension). How would I do this? I am presently using this Bash function:

function manhtmlp {
  for i in `equery files "$1" | grep /usr/share/man/man`
    bzcat $i | mandoc -Thtml > $HOME/GitHub/fusion809.github.io/man/${i}.html
    sudo chmod 777 -R $HOME/GitHub/fusion809.github.io/man/${i}.html

on the fifth and sixth lines I use the notation ${i} to indicate where I would like to be able to prune the man page's full path for its file name (without its extension). The user-supplied input (denoted by $1 in this function) denotes the name of a package, including its category (e.g., it would equal sys-apps/portage for the Portage package manager).

EDIT: Why this question is distinct from Stripping directory paths to get file names.

This previous question's answers while similar to what I would like do not tell one how to strip file extensions away from file names, only the rest of their path. So in the example of /usr/share/man/man5/xpak.5.bz2 the answer to the aforementioned question would provide one a way to get xpak.5.bz2 out of this full file path, but not xpak.5.

  • This may helpful: basename /usr/share/man/man5/xpak.5.bz2 | sed 's/\(.*\)\..*/\1/' will return file-name without extension! – Pandya Dec 18 '15 at 6:19

Using parameter expansion:

 # printf "%s\n" "${line##*/}"                                     
 # xpak.5.bz2
printf "%s\n" "${file%.*}"

In Zsh, you can do nested parameter expansions:

printf "%s\n" "${${line##*/}%.*}"
  • Definitely sounds like you're on the right track, but is there a way to do this in a single line, say with the dummy variable $i? Like would ${i##*/%.*} do the trick? – Josh Pinto Dec 18 '15 at 6:20
  • @BrentonHorne I think you can play with your grep expression, for example this strips out the directory paths: grep -Po '/usr/share/man/man.*/\K[^/]+\.bz2$' (hat-tip to this SO answer on how to use \K with the -Po flags) – h.j.k. Dec 18 '15 at 7:48

Using basename:

       basename - strip directory and suffix from filenames

       basename NAME [SUFFIX]
       basename OPTION... NAME...

       Print NAME with any leading directory components removed.  If specified, also remove a trailing SUFFIX.


$ file="/usr/share/man/man5/xpak.5.bz2"
$ echo "$(basename "$file" .bz2)"

You can also use sed if suffix is unknown:

$ file="/usr/share/man/man5/xpak.5.bz2"
$ echo "$(basename "$file" | sed 's/\(.*\)\..*/\1/')"
$ xpark.5
  • 1
    Note, basename requires an additional process (as, more obviously, does sed)... – jasonwryan Dec 18 '15 at 6:52

Not the answer you're looking for? Browse other questions tagged or ask your own question.