In Bourne-like shells, you create environment variables by marking a shell variable with the export
attribute (so it's exported to the environment of the commands that the shell will execute) by using the export
builtin utility:
export BWD
To assign a value to a shell variable, the syntax is:
BWD=value
You can make that value the output of command by using command substitution. In the Bourne shell, that was with the `the-command`
syntax, but in modern Bourne-like shells, the preferred way is with $(the-command)
instead:
BWD=$(the-command)
Usually, you need quotes around command substitutions to prevent split+glob. However, split+glob doesn't occur in assignments to scalar variables, so they're not necessary here.
The command to get the base name of a file path is the basename
command.
basename "$PWD"
(the quotes there are necessary as split+glob does occur in arguments to commands).
That would return the base name of the file stored in $PWD
, unless that value starts with -
, in which case, YMMV as many basename
implementations will treat it as an option. So generally, when passing variable data to command, we use a --
to tell the command that what's after is not to be taken as an option even if it starts with -
(here, $PWD
should always start with /
except in very pathological cases, so it's not strictly needed).
BWD=$(basename -- "$PWD")
export BWD
In modern shells, you can combine both with:
export BWD="$(basename -- "$PWD")"
(the quotes are needed in some implementations as we're back in the arguments of commands, though some other implementations do parse the arguments of export
like assignments as a special case under some conditions).
One problem with that approach is if the value of $PWD
ends in newline characters (unlikely in practice) as command substitution strips all trailing newline characters. So in:
mkdir $'foo\n\n'
cd $'foo\n\n'
export BWD="$(basename -- "$PWD")"
$BWD
will contain foo
instead of $'foo\n\n'
.
Instead, you may want to use shell builtin operators to get that base name. In zsh
, that can be done with $PWD:t
(t
for tail); in all POSIX-like shells (including zsh), that can be done with ${PWD##*/}
which removes everything up to the right-most /
from the content of $PWD
.
It will give a different result however if $PWD
is /
. In that case, basename
returns /
but ${PWD##*/}
or $PWD:t
expand to the empty string instead. For a directory like /foo/bar/
($PWD
usually doesn't end in /
though except for /
itself), basename
and $PWD:t
give bar
, while ${PWD##*/}
give the empty string again.
For a variable that dynamically expands to the basename of $PWD
, you may use ksh93
and its discipline function:
ksh93
also has a builtin version of basename
provided you have /opt/ast/bin
ahead of $PATH
. So in ksh93:
$ PATH=/opt/ast/bin:$PATH
$ type basename
basename is a shell builtin version of /opt/ast/bin/basename
$ BWD.get() { .sh.value=${ basename -- "$PWD"; }; }
$ cd /var/log
$ echo "$BWD"
log
$ cd /usr/local
$ echo "$BWD"
local
$ export BWD
$ printenv BWD
local
Above, we're using a ksh93-specific form of command substitution: ${ the-command; }
which is more efficient in that it doesn't create a subshell environment to run the command.
For the bash
shell, see Prevent command substitution from running when declaring a variable for some approaches.
BWD
whencd
is used:cd () { builtin cd "$@" && BWD=${PWD##*/}; }
. – Kusalananda Jan 07 '19 at 20:35trap 'BWD=${PWD##*/}' DEBUG
:-) – Stephen Harris Jan 07 '19 at 20:39echo
commands as well. – kasperd Jan 08 '19 at 09:16