Pregunta

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.

¿Fue útil?

Solución

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

Otros consejos

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
/
Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top