My preferred terminal for daily use is fish. Quite often I have to split a path and extract the filename from it. Unlike Bash, fish does not have basename utility. I use sed to extract the filename from the path.

It made sense to create a function so that I wouldn’t have to keep repeating the same regex.

Fish Function

1
2
3
function tm_split_path -d 'Return filename, ext, and directory from the path'
    echo $argv[1] | sed 's/\(.*\)\/\(.*\)\.\(.*\)$/\2\n\3\n\1/'
end
Line 1

Function name is tm_split_path. I prefer to prefix my shell functions with a common prefix. This way, I don’t have to recall the function name. I just type tm_ and press tab key. Fish shell automatically suggests the list of possible functions.

What follows -d is the description of the function. It appears in the list of suggestions. Notice the description in highlighted line in the following list.

fish shell suggestion list demo

Line 2
$argv is the variable which contains the arguments passed to the function. It’s an array.

Remember

Array index in Fish starts from 1, not 0.

sed expression

I have written in detail about sed expression here.

Here is an example output,

$ echo "/User/talha/content/images/README.example.md" | sed 's/\(.*\)\/\(.*\)\.\(.*\)$/\1\n\2\n\3/'
README.example
md
/User/talha/content/images

Return Array

\n in the replace pattern of sed expression is important. Each part of the pathname is printed on the newline.

Fish automatically converts the input that has newlines into an array.

Create Array In Fish

  1. List every item on a new line
  2. Capture those lines in a command substitution

Now I can use the function, tm_split_path, from other fish functions or scripts this way:

set result (tm_split_path "/Library/Extensions/File.kex")
echo Filename: $res[1]
echo Extensiion: $res[2]
echo Directory: $res[3]

(tm_split_path "/Library/Extensions/File.kex") prints the filename, extension and directory, each on its own line.

set assigns those three lines to result variable.

Fish automatically assumes that the result is an array because of the new lines present.

This way, I can refer to filename, extension and, directory using array indices, like

  1. $res[1] for filename
  2. $res[2] for extension
  3. $res[3] for directory

Example

You can view complete script here.

This script also handles the case when the given argument does not have directory in it, like “filename.ext”.

Like this post? Share on: TwitterFacebookEmail

Comments

So what do you think? Did I miss something? Is any part unclear? Leave your comments below.
You need a free Github account to comment.


Keep Reading


Published

Last Updated

Category

Fish Shell

Tags

Stay in Touch