0

I'm trying to parsearg arguments to pass options to the script.

but it is showing the following errors Unexpected option: -u in addition to looping below:

$ gitpratico -u "<usuario_github>" -p "<repositorio_remoto_github>" -c "comentario criação/alteração repositorio"

Unexpected option: -u

O gitpratico deve ser executado dentro da pasta do projeto somente uma unica vez

Enter: gitpratico [ -u "user_git" | --user ] [ -p "project_name" | --proj ] 
    [ -c "comemt alter project" | --commit ] [ -h | --help]
    

Unexpected option: -u

O gitpratico deve ser executado dentro da pasta do projeto somente uma unica vez

Enter: gitpratico [ -u "user_git" | --user ] [ -p "project_name" | --proj ] 
    [ -c "comemt alter project" | --commit ] [ -h | --help]
    

Unexpected option: -u

O gitpratico deve ser executado dentro da pasta do projeto somente uma unica vez

Enter: gitpratico [ -u "user_git" | --user ] [ -p "project_name" | --proj ] 
    [ -c "comemt alter project" | --commit ] [ -h | --help]

How do I solve this problem?

I tried using getopt but it didn't work.

SHORT=c:p:u:h
LONG=commit:proj:user:help
OPTS=$(getopt -a -n ${0##*/} --options $SHORT --longoptions $LONG -- "$@")
#!/bin/bash

GIT="$(which git)"

CURL="$(which curl)"

#USER_GIT="${1}"

#PROJECT_NAME="${2}"

<<COMENTARIO
O script "gitpratico_multiuser" foi criado para mais de um usuario que tem acesso 
a mesma estação de trablho em horarios diferentes possa usar o script sem 
precisar ficar digitando a chave token toda vez que usar o script,
basta colocar a "chave token" de todos os usuarios github e os usuario github 
no vetor deste script assim se tivermos tres usuarios 
que acessam a maquina em horarios diferentes todos eles tem que 
estar configurados no vetor com suas respectivas chaves tokens 
na mesma posição em que se encontra o seu usuario no vetor 
e o ssh configurado no github entao basta 
apenas digitar "gitpratico <username_git> <nome_projeto>" para criar os repositorios.
COMENTARIO

USERS_GIT=("usuario1" "usuario2" "github_usuario3")

## Pegando os hosts dos usuarios githubs em ~/.ssh/config e colocando no Vetor
HOSTS_GITHUB_USERS=($(grep "host-" ~/.ssh/config | sed 's/Host\s//g;'))

#Coloque sua chave token no vetor para verificar
ACESS_TOKEN=("chave1" chave2" "chave_token_github_usuario3")

function help(){
    echo
    echo "O ${0##*/} deve ser executado dentro da pasta do projeto somente uma unica vez"
    echo
    echo -e "Usage: ${0##*/} [ -u \"user_git\" | --user ] [ -p \"project_name\" | --proj ] 
    [ -c \"comemt alter project\" | --commit ] [ -h | --help]
    "
    echo
}

#SHORT=c:p:u:h
#LONG=commit:proj:user:help
#OPTS=$(getopt -a -n ${0##*/} --options $SHORT --longoptions $LONG -- "$@")

if [ $# -lt 3 ]; then
  help
   else

##Os c:p:u:user:proj:commit: [obriga a digitar um argumento após a opção]
while getopts c:p:u:user:proj:commit:h,help option
do
  case "${option}" in
    "-u" |" --user")
     USER_GIT="${OPTARG}"
    ;;
    "-p" | "--proj")
     PROJECT_NAME="${OPTARG}"
    ;;
    
   "-c"|"--commit")
    COMENTARIO="${OPTARG}"
   ;;

   "-h"|"--help")
    help
   ;;

   --)
    help
   ;;

   *)
     echo "Unexpected option: ${1}"
     help
    ;;
  esac
done
    
for ((i = 0; i < "${#USERS_GIT[@]}"; i++))
    do
       
        if [[ "${USERS_GIT[$i]}" == "${USER_GIT}" ]]; then
            
            #Criando os repositprios remotamente sem logar no github
            ${CURL} -i -H "Authorization: token ${ACESS_TOKEN[$i]}" -d "{\"name\":\"${PROJECT_NAME}\",\"private\":false}" https://api.github.com/user/repos
            
            if [[ "${PROJECT_NAME}" != "${PWD[@]/*\/}" ]]; then
                
                mkdir ${PROJECT_NAME}
                
                cd ${PROJECT_NAME}
                
                #Inicializa o repositório
                ${GIT[@]/*\/} init
                
                ##Cria um README no projeto
                echo "## README ${PROJECT_NAME}" >> README.md
                echo "### PROJETO criado com o script gitpratico" >> README.md
                
                ## Adiciona todos os arquivos existentes na pasta
                ${GIT[@]/*\/} add .
                
                #echo "Digite um comentário sobre o que você fez no projeto: "
                #echo
                #read -p "Entre com o comentario: " COMENTARIO
                
                ##Comitando o projeto
                ${GIT[@]/*\/} commit -m "${COMENTARIO}"
                
                #Modifica o branch atual criado pelo commit
                ${GIT[@]/*\/} branch -M main
                
                #Apos fazer qualquer alteração estas configurações permiten fazer apenas "git push" no projeto
                #Sem precisar digitar toda vez: git push [email protected]:$USERS_GIT/${PROJECT_NAME}.git main
                #Todos os repositórios criados com o script terão "branch master"
                
echo "[core]
        repositoryformatversion = 0
        filemode = true
        bare = false
        logallrefupdates = true
[remote \"origin\"]
        url = git@${HOSTS_GITHUB_USERS[${i}]}:${USERS_GIT[${i}]}/${PROJECT_NAME}.git
        fetch = +refs/heads/*:refs/remotes/origin/*
[branch \"main\"]
        remote = origin
        merge = refs/heads/main"> .git/config

                echo "Copie e cole seu token caso nescessário ou digite a senha configurada na chave ssh do github"
                echo
                ${GIT[@]/*\/} push git@${HOSTS_GITHUB_USERS[${i}]}:${USERS_GIT[${i}]}/${PROJECT_NAME}.git main
            
            elif [[ ${PROJECT_NAME} == ${PWD[@]/*\/} ]]; then
                
                README="$(ls -1 README.md 2> /dev/null)"
                
                #Inicializa o repositório
                ${GIT[@]/*\/} init
                
                if [ -z "${README}" ]; then
                    ##Cria um README caso o projeto nao tenha nada na pasta ainda
                    echo "## README ${PROJECT_NAME}" >> README.md
                    echo "### PROJETO criado com o script gitpratico" >> README.md
                else
                    echo "### PROJETO criado com o script gitpratico" >> README.md
                fi
                
                ## Adiciona todos os arquivos existentes na pasta
                ${GIT[@]/*\/} add .
                
                #echo "Digite um comentário sobre o que você fez no projeto: "
                #echo
                #read -p "Entre com o comentario: " COMENTARIO
                
                ##Comitando o projeto
                ${GIT[@]/*\/} commit -m "${COMENTARIO}"
                
                #Modifica o branch atual criado pelo commit
                ${GIT[@]/*\/} branch -M main
                
                #Apos fazer qualquer alteração estas configurações permiten fazer apenas "git push" no projeto
                #Sem precisar digitar toda vez: git push [email protected]:${USER_GIT}/${PROJECT_NAME}.git main
                #Todos os repositórios criados com o script terão "branch master"
                
echo "[core]
        repositoryformatversion = 0
        filemode = true
        bare = false
        logallrefupdates = true
[remote \"origin\"]
        url = git@${HOSTS_GITHUB_USERS[${i}]}:${USERS_GIT[${i}]}/${PROJECT_NAME}.git
        fetch = +refs/heads/*:refs/remotes/origin/*
[branch \"main\"]
        remote = origin
        merge = refs/heads/main"> .git/config
                
                echo "Copie e cole seu token caso nescessário ou digite a senha configurada na chave ssh do github"
                echo
                ${GIT[@]/*\/} push git@${HOSTS_GITHUB_USERS[${i}]}:${USERS_GIT[${i}]}/${PROJECT_NAME}.git main

            fi #Fim PWD

        fi #Fim USERS_GIT
        
done #Fim for

My script alter this:

#!/bin/bash

GIT="$(which git)"

CURL="$(which curl)"

#USER_GIT="${1}"

#PROJECT_NAME="${2}"

<<COMENTARIO
O script "gitpratico_multiuser" foi criado para mais de um usuario que tem acesso 
a mesma estação de trablho em horarios diferentes possa usar o script sem 
precisar ficar digitando a chave token toda vez que usar o script,
basta colocar a "chave token" de todos os usuarios github e os usuario github 
no vetor deste script assim se tivermos tres usuarios 
que acessam a maquina em horarios diferentes todos eles tem que 
estar configurados no vetor com suas respectivas chaves tokens 
na mesma posição em que se encontra o seu usuario no vetor 
e o ssh configurado no github entao basta 
apenas digitar "gitpratico <username_git> <nome_projeto>" para criar os repositorios.
COMENTARIO

USERS_GIT=("usuario1" "usuario2" "github_usuario3")

## Pegando os hosts dos usuarios githubs em ~/.ssh/config e colocando no Vetor
HOSTS_GITHUB_USERS=($(grep "host-" ~/.ssh/config | sed 's/Host\s//g;'))

#Coloque sua chave token no vetor para verificar
ACESS_TOKEN=("chave1" "chave2" "chave_token_github_usuario3")

function help(){
    
    echo -e "\nO ${0##*/} deve ser executado dentro da pasta do projeto somente uma unica vez\n"
    echo -e "Usage: ${0##*/} [ -u \"user_git\" | --user ]\n\n[ -p \"project_name\" | --proj ]\n\n[ -c \"comemt alter project\" | --commit ]\n\n[ -h | --help]\n\n"
}

if [ $# -lt 3 ]; then
  help
   else

##Os : [obriga a digitar um argumento após a opção u,p,user,proj]
while getopt u:p:c:user:proj:coment:h,help option
do
  case "${option}" in
    -u|--user)
     USER_GIT="${OPTARG}"
    ;;
    -p|--proj)
     PROJECT_NAME="${OPTARG}"
    ;;

    -c|--coment)
    COMENTARIO="${OPTARG}"
    ;;
    
   -h|--help)
    help
   ;;

   --)
    help
   ;;

   *)
     echo "Unexpected option: ${1}"
     help
    ;;
  esac
done
    
for ((i = 0; i < "${#USERS_GIT[@]}"; i++))
    do
       
        if [[ "${USERS_GIT[$i]}" == "${USER_GIT}" ]]; then
            
            #Criando os repositprios remotamente sem logar no github
            ${CURL} -i -H "Authorization: token ${ACESS_TOKEN[$i]}" -d "{\"name\":\"${PROJECT_NAME}\",\"private\":false}" https://api.github.com/user/repos
            
            if [[ "${PROJECT_NAME}" != "${PWD[@]/*\/}" ]]; then
                
                mkdir ${PROJECT_NAME}
                
                cd ${PROJECT_NAME}
                
                #Inicializa o repositório
                ${GIT} init
                
                ##Cria um README no projeto
                echo "## README ${PROJECT_NAME}" >> README.md
                echo "### PROJETO criado com o script gitpratico" >> README.md
                
                ## Adiciona todos os arquivos existentes na pasta
                ${GIT} add .
                
                #echo "Digite um comentário sobre o que você fez no projeto: "
                #echo
                #read -p "Entre com o comentario: " COMENTARIO
                
                ##Comitando o projeto
                ${GIT} commit -m "${COMENTARIO}"
                
                #Modifica o branch atual criado pelo commit
                ${GIT} branch -M main
                
                #Apos fazer qualquer alteração estas configurações permiten fazer apenas "git push" no projeto
                #Sem precisar digitar toda vez: git push [email protected]:$USERS_GIT/${PROJECT_NAME}.git main
                #Todos os repositórios criados com o script terão "branch master"
                
echo "[core]
        repositoryformatversion = 0
        filemode = true
        bare = false
        logallrefupdates = true
[remote \"origin\"]
        url = git@${HOSTS_GITHUB_USERS[${i}]}:${USERS_GIT[${i}]}/${PROJECT_NAME}.git
        fetch = +refs/heads/*:refs/remotes/origin/*
[branch \"main\"]
        remote = origin
        merge = refs/heads/main"> .git/config

                echo "Copie e cole seu token caso nescessário ou digite a senha configurada na chave ssh do github"
                echo
                ${GIT} push git@${HOSTS_GITHUB_USERS[${i}]}:${USERS_GIT[${i}]}/${PROJECT_NAME}.git main
            
            elif [[ ${PROJECT_NAME} == ${PWD[@]/*\/} ]]; then
                
                README="$(ls -1 README.md 2> /dev/null)"
                
                #Inicializa o repositório
                ${GIT} init
                
                if [ -z "${README}" ]; then
                    ##Cria um README caso o projeto nao tenha nada na pasta ainda
                    echo "## README ${PROJECT_NAME}" >> README.md
                    echo "### PROJETO criado com o script gitpratico" >> README.md
                else
                    echo "### PROJETO criado com o script gitpratico" >> README.md
                fi
                
                ## Adiciona todos os arquivos existentes na pasta
                ${GIT} add .
                
                #echo "Digite um comentário sobre o que você fez no projeto: "
                #echo
                #read -p "Entre com o comentario: " COMENTARIO
                
                ##Comitando o projeto
                ${GIT} commit -m "${COMENTARIO}"
                
                #Modifica o branch atual criado pelo commit
                ${GIT} branch -M main
                
                #Apos fazer qualquer alteração estas configurações permiten fazer apenas "git push" no projeto
                #Sem precisar digitar toda vez: git push [email protected]:${USER_GIT}/${PROJECT_NAME}.git main
                #Todos os repositórios criados com o script terão "branch master"
                
echo "[core]
        repositoryformatversion = 0
        filemode = true
        bare = false
        logallrefupdates = true
[remote \"origin\"]
        url = git@${HOSTS_GITHUB_USERS[${i}]}:${USERS_GIT[${i}]}/${PROJECT_NAME}.git
        fetch = +refs/heads/*:refs/remotes/origin/*
[branch \"main\"]
        remote = origin
        merge = refs/heads/main"> .git/config
                
                echo "Copie e cole seu token caso nescessário ou digite a senha configurada na chave ssh do github"
                echo
                ${GIT} push git@${HOSTS_GITHUB_USERS[${i}]}:${USERS_GIT[${i}]}/${PROJECT_NAME}.git main

            fi #Fim PWD

        fi #Fim USERS_GIT
        
done #Fim for

fi

I removed this error from the script and even so it keeps looping infinitely and showing Unexpected option I changed getopts to getopt

Unexpected option: -u and others

4
  • 2
    have a look at the syntax highlighting of the code here, it shows big parts of your script colored as quoted strings. Starting from this line ACESS_TOKEN=("chave1" chave2" "chave_token_github_usuario3"), there's an orphan double-quote in the middle there
    – ilkkachu
    Commented Apr 25, 2023 at 9:31
  • 1
    yep, that's a quoting bug, i.e., a typo :) add the missing " before chave2" and you'll be fine. (and, as @ilkkachu says, an editor with working syntax highlighting might have saved you there. Set up your neovim/spacemacs/kate… correctly!) Anyway, this typo should have lead to something like a syntax error in ACCESS_TOKEN=( or "cannot find O" or such, so I'm not sure the code we're looking at is actually the exact code that leads to your problem! Commented Apr 25, 2023 at 9:33
  • from the way SE renders it, it looks like | signs in help() are unquoted, and they're likely to be something that should give a syntax error
    – ilkkachu
    Commented Apr 25, 2023 at 9:39
  • You really don't want to use CAPS for shell variable names. Since, by convention, global environment variables are capitalized, it is bad practice to also use caps for your own, local variables because this can lead to naming collisions and hard to find bugs.
    – terdon
    Commented Apr 25, 2023 at 9:43

2 Answers 2

1

(For the sake of brevity, this answer concentrates on the option parsing bug in the code, which is what the question asks about, but ignores any other issue the code may possibly have.)

Apart from not supporting long options, the standard getopts utility will place the option character without a dash in the given variable.

This means the case statement in your command line parsing loop should be changed to test for u, p, c, and h, without the dashes. The error message in the * case might also be changed to mention -$option rather than $1 as the latter may be unrelated to the unknown option. It could also be argued that outputting the error message should be followed by exit 1, as no further processing is likely to be possible.

1

getopts (with the s) is a standard utility, and doesn't support long options, so getopts c:p:u:user:proj:commit:h means c, p and u etc. are options that take an arg, and u, s, e, r etc. are (single-char) options that don't. I don't know what it does if you specify a letter twice there.

If you're going to use getopt (without the s) instead, you're going to need the enhanced one from util-linux or Busybox, and you need to take care to use it properly. See e.g. my older answer here (reference chosen because it was easiest to find.) Traditional getopt implementations barf at whitespace etc., in addition to also not supporting long options.

Also, even though getopts is implemented in the shell, it doesn't itself change the positional parameters. So when you print that error with echo "Unexpected option: ${1}" you always print the actual first argument to the script, which is likely unrelated to the error in question. E.g. here, it's always -a you get from $1:

$ sh -c 'while getopts ab opt; do echo "$opt $1"; done' sh -a -b -c
a -a
b -a
Illegal option -c
? -a
1
  • I removed this error from the script and even so it keeps looping infinitely and showing Unexpected option I changed getopts to getopt
    – user569757
    Commented Apr 25, 2023 at 21:20

You must log in to answer this question.