phil swenson
phil swenson

Reputation: 8894

best way to find top-level directory for path in bash

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!

Upvotes: 3

Views: 9235

Answers (5)

Charles Duffy
Charles Duffy

Reputation: 295403

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.

Upvotes: 2

Matias Barrios
Matias Barrios

Reputation: 5056

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!

Upvotes: 0

zzevannn
zzevannn

Reputation: 3714

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.

Upvotes: 0

karakfa
karakfa

Reputation: 67497

not sure better but with sed

$ echo "/go/src/github.myco.com/viper-ace/psn-router" | sed -E 's_(/[^/]+).*_\1_'
/go

Upvotes: 1

anubhava
anubhava

Reputation: 785128

One option is using awk:

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

/go

Upvotes: 7

Related Questions