21

Given ANY GitHub repository url string like:

git://github.com/some-user/my-repo.git

or

git@github.com:some-user/my-repo.git

or

https://github.com/some-user/my-repo.git

What is the best way in bash to extract the repository name my-repo from any of the following strings? The solution MUST work for all types of urls specified above.

Thanks.

9 Answers 9

25
$ url=git://github.com/some-user/my-repo.git
$ basename=$(basename $url)
$ echo $basename
my-repo.git
$ filename=${basename%.*}
$ echo $filename
my-repo
$ extension=${basename##*.}
$ echo $extension
git
3
  • Thanks, trying to make it a one liner, but not working. REPO_NAME=${`basename $REPO_URL`%.*}
    – Justin
    Aug 14, 2012 at 4:17
  • 2
    echo $(basename "$url" ".${url##*.}").
    – quanta
    Aug 14, 2012 at 6:31
  • +1. Is there anything similar to get the hostname, i.e. github.com, instead, @quanta?
    – chepukha
    Mar 31, 2015 at 2:19
22

I'd go with basename $URL .git.

1
  • 1
    the best answer. The shortest as well Apr 22, 2020 at 9:23
14

Old post, but I faced the same problem recently.

The regex ^(https|git)(:\/\/|@)([^\/:]+)[\/:]([^\/:]+)\/(.+).git$ works for the three types of URL.

#!/bin/bash

# url="git://github.com/some-user/my-repo.git"
# url="https://github.com/some-user/my-repo.git"
url="git@github.com:some-user/my-repo.git"

re="^(https|git)(:\/\/|@)([^\/:]+)[\/:]([^\/:]+)\/(.+)(.git)*$"

if [[ $url =~ $re ]]; then    
    protocol=${BASH_REMATCH[1]}
    separator=${BASH_REMATCH[2]}
    hostname=${BASH_REMATCH[3]}
    user=${BASH_REMATCH[4]}
    repo=${BASH_REMATCH[5]}
fi

Explaination (see it in action on regex101):

  • ^ matches the start of a string
  • (https|git) matches and captures the characters https or git
  • (:\/\/|@) matches and captures the characters :// or @
  • ([^\/:]+) matches and captures one character or more that is not / nor :
  • [\/:] matches one character that is / or :
  • ([^\/:]+) matches and captures one character or more that is not / nor :, yet again
  • [\/:] matches the character /
  • (.+) matches and captures one character or more
  • (.git)* matches optional .git suffix at the end
  • $ matches the end of a string

This if far from perfect, as something like https@github.com:some-user/my-repo.git would match, but I think it's fine enough for extraction.

4
  • 🏆this is gold!
    – Omri
    Jul 1, 2018 at 14:24
  • 1
    some urls don't have .git at the end.
    – kenn
    Jan 2, 2019 at 14:58
  • @kenn: then they'd not be a valid remote for git, however. See git-scm.com/docs/git-push#URLS. Feb 9, 2022 at 12:06
  • 1
    I'm using an expanded version (play with it on regex101: ^((https?|ssh|git|ftps?):\/\/)?(([^\/@]+)@)?([^\/:]+)[\/:]([^\/:]+)\/(.+).git\/?$, which better matches the official spec for URLs. Group 2 is the scheme, if missing the default is ssh. Feb 9, 2022 at 12:13
6

Summing up:

  • Get url without (optional) suffix:

    url_without_suffix="${url%.*}"
    
  • Get repository name:

    reponame="$(basename "${url_without_suffix}")"
    
  • Get user (host) name afterwards:

    hostname="$(basename "${url_without_suffix%/${reponame}}")"
    
1

use regular expression: /([^/]+)\.git$/

0
basename $git_repo_url | tr -d ".git"
0

basename is my favorite, but you can also use sed:

url=git://github.com/some-user/my-repo.git
reponame="$(echo $url | sed -r 's/.+\/([^.]+)(\.git)?/\1/')"
# reponame = "my-repo"

"sed" will delete all text until the last / + the .git extension (if exists), and will retain the match of group \1 which is everything except dot ([^.]+)

0

Using Hitcham's awesome answer above allowed me to come up with this, using sed to output exactly what needed: org/reponame with sed.

output = echo ${git_url} | sed -nr  's/^(https|git)(:\/\/|@)([^\/:]+)[\/:]([^\/:]+)\/(.+).git$$/\4\/\3/p'`

Works well in ubuntu, doesn't work for the sed available by default on macosx.

0

A slight modification to @Hicham's answer

^(https|git)(:\/\/|@)([^\/:]+)[\/:]([^\/:]+)\/(.+?)(\.git)?$

Will extract out the .git suffix as well.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge that you have read and understand our privacy policy and code of conduct.

Not the answer you're looking for? Browse other questions tagged or ask your own question.