1

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,284
  • 20
  • 71
  • 96

5 Answers5

3

One option is using awk:

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

/go
anubhava
  • 713,503
  • 59
  • 514
  • 593
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
  • 257,635
  • 38
  • 339
  • 400
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
  • 2,859
  • 1
  • 11
  • 20
0

not sure better but with sed

$ echo "/go/src/github.myco.com/viper-ace/psn-router" | sed -E 's_(/[^/]+).*_\1_'
/go
karakfa
  • 64,710
  • 7
  • 38
  • 55
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,123
  • 2
  • 15
  • 39