Suppose I have a string in my variable as follows.
var="/fnxn/ngfdg/abc.ext"
I can get the root of this variable (remove extension .*) as follows
echo ${var%.*}
I can get the tail of this variable (removing the path */) as follows
echo ${var##*/}
But now I have to remove both the path and the extension. I can do it in two step using another variable as follows.
var2=${var##*/}
var3=${var2%.*}
But the single step option (similar to zsh syntax below) shows an error message "bad substitution" in bash.
echo ${${var##*/}%.*}
It would be useful if I get a single step comprehensible option to reduce the code length and avoid additional environment variable.
Best Answer
If you have a fixed extension, POSIX
basename
supports exactly the cropping you're attempting:If you don't, zsh expansion supports exactly what you're trying:
So in zsh
will do what you expected.
If you're committed to Bash, and you want to save lines, you could use sed:
That's just a regular-expression replacement of everything after the last
.
with nothing, after losing the prefix the same way you are now. I don't see this particularly saving memory over the two-line version, however, and it's probably less comprehensible too.Note that there's no reason you can't use the same variable right through the process:
The expansion happens before the assignment, so this is safe. If your concern is a really long filename being stored twice, that won't happen now, but I don't think that is a realistic problem.