2

I need a command that will return the top level base directory for a specified path in bash.

I have an approach that works, but seems ugly:

echo "/go/src/github.myco.com/viper-ace/psn-router" | cut -d "/" -f 2 | xargs printf "/%s"

It seems there is a better way, however all the alternatives I've seen seem worse.

Thanks for any suggestions!

phil swenson
  • 8,564
  • 20
  • 74
  • 99

5 Answers5

5

One option is using awk:

echo "/go/src/github.myco.com/viper-ace/psn-router" |
awk -F/ '{print FS $2}'

/go
anubhava
  • 761,203
  • 64
  • 569
  • 643
2

As a native-bash approach forking no subshells and invoking no other programs (thus, written to minimize overhead), which works correctly in corner cases including directories with newlines:

topdir() {
    local re='^(/+[^/]+)'
    [[ $1 =~ $re ]] && printf '%s\n' "${BASH_REMATCH[1]}"
}

Like most other solutions here, invocation will then look something like outvar=$(topdir "$path").


To minimize overhead even further, you could pass in the destination variable name rather than capturing stdout:

topdir() {
    local re='^(/+[^/]+)'
    [[ $1 =~ $re ]] && printf -v "$2" '%s' "${BASH_REMATCH[1]}"
}

...used as: topdir "$path" outvar, after which "$outvar" will expand to the result.

Charles Duffy
  • 280,126
  • 43
  • 390
  • 441
1

not sure better but with sed

$ echo "/go/src/github.myco.com/viper-ace/psn-router" | sed -E 's_(/[^/]+).*_\1_'
/go
karakfa
  • 66,216
  • 7
  • 41
  • 56
0

Here's a sed possibility. Still ugly. Handles things like ////////home/path/to/dir. Still blows up on newlines.

$ echo "////home/path/to/dir" | sed 's!/*\([^/]*\).*!\1!g'
/home

Newlines breaking it:

$ cd 'testing '$'\n''this' 
$ pwd
/home/path/testing
this
$ pwd | sed 's!/*\([^/]*\).*!/\1!g'
/home
/this

If you know your directories will be rather normally named, your and anubhava's solutions certainly seem to be more readable.

zzevannn
  • 3,414
  • 2
  • 12
  • 20
0

This is bash, sed and tr in a function :

#!/bin/bash




function topdir(){
  dir=$( echo "$1" | tr '\n' '_' )
  echo "$dir" | sed -e 's#^\(/[^/]*\)\(.*\)$#\1#g'
}



topdir '/go/src/github.com/somedude/someapp'

topdir '/home/somedude'

topdir '/with spaces/more here/app.js'

topdir '/with newline'$'\n''before/somedir/somefile.txt'

Regards!

Matias Barrios
  • 4,674
  • 3
  • 22
  • 49