Question

For GNU Screen titling purposes, I'd like to get ahold of the current directory name prefixed by the name of its parent. For example, within directories

/home/rhys/share/pkgconfig
/home/rhys
/home
/

producing outputs

share/pkgconfig
home/rhys
home
/

In Bash, starting from a guess like

echo $(basename $(dirname $PWD))/$(basename $PWD)

one can arrive at a better solution

echo $(basename "${PWD%/*}")/${PWD##*/}

where I say better because two fewer processes are spawned.

Anyone have a cute trick to avoid using basename at all? This is for something run every shell prompt so it'd be nice to be as lightweight as possible.

Was it helpful?

Solution

for p in /home/rhys/share/pkgconfig /home/rhys /home /; do
  [[ $p =~ .*/([^/]+/[^/]+)$ ]] && echo "${BASH_REMATCH[1]}" || echo "$p"
done

As a function:

last2() { [[ $1 =~ .*/([^/]+/[^/]+)$ ]] && echo "${BASH_REMATCH[1]}" || echo "$1"; }

Should work on bash >= 3.2

OTHER TIPS

How about this, using bash and awk:

awk -F'/' '{print $(NF-1)"/"$NF}' <<<"$PWD"

Edit

The previous one is not quite right, as it prints /home rather than just home. Maybe you can live with that. If not, this one works fully:

awk -F'/' '{if (NF==2 && $2) {$0=$2} else {$0=$(NF-1)"/"$NF}}1' <<<"$PWD"

Testing it out:

awk -F'/' '{if (NF==2 && $2) {$0=$2} else {$0=$(NF-1)"/"$NF}}1' <<EOF
/home/rhys/share/pkgconfig
/home/rhys
/home
/
EOF

Output:

share/pkgconfig
home/rhys
home
/

Here's a function that will work in bash 4 or later:

trim () (
  IFS=/
  read -a c <<< "$1"
  unset c[0]
  fragment="${c[*]: -2:2}"
  echo "${fragment:-/}"
)

for p in /home/rhys/share/pkgconfig /home/rhys /home /; do
  trim "$p"
done

share/pkgconfig
home/rhys
home
/
Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top