Verifique se a variável do shell contém um caminho absoluto

4

Eu quero verificar se uma variável do shell contém um caminho absoluto.

Eu não me importo se o caminho existe ou não - se não o criar, mas quero garantir que estou lidando com um nome de caminho absoluto.

Meu código é parecido com o seguinte:

myfunction() {
  [ magic test to see if "$1" is an absolute path ] || return 1
  mkdir -p "$(dirname "$1")" || return 1
  commands >> "$1"
}

Ou o caso de uso em que o caminho absoluto a ser verificado se destina a ser um diretório:

anotherfunction() {
  [ same magic test ] || return 1
  mkdir -p "$1"
  dostuff >> "$1/somefile"
}

Se este fosse awk eu faria o check assim: myvar ~ /^\//

A deve ser uma maneira limpa de fazer isso com o tratamento de strings do shell, mas estou tendo problemas para criar isso.

(Mencionar uma solução bash específica seria ótimo, mas eu gostaria de saber como fazer isso de forma portável, também. A manipulação de strings POSIX parece ser suficiente para isso.)

    
por Wildcard 20.01.2016 / 01:57

7 respostas

6

Você pode apenas fazer:

case $1 in (/*) pathchk -- "$1";; (*) ! : ;; esac

Isso deve ser o suficiente. E ele gravará diagnósticos para stderr e retornará a falha por componentes inacessíveis ou inacessíveis. pathchk não é sobre os nomes existentes - é sobre < em> usáveis nomes de caminho.

The pathchk utility shall check that one or more pathnames are valid (that is, they could be used to access or create a file without causing syntax errors) and portable (that is, no filename truncation results). More extensive portability checks are provided by the -p option.

By default, the pathchk utility shall check each component of each pathname operand based on the underlying file system. A diagnostic shall be written for each pathname operand that:

  • Is longer than {PATH_MAX} bytes (see Pathname Variable Values in <limits.h>)

  • Contains any component longer than {NAME_MAX} bytes in its containing directory

  • Contains any component in a directory that is not searchable

  • Contains any character in any component that is not valid in its containing directory

The format of the diagnostic message is not specified, but shall indicate the error detected and the corresponding pathname operand.

It shall not be considered an error if one or more components of a pathname operand do not exist as long as a file matching the pathname specified by the missing components could be created that does not violate any of the checks specified above.

    
por 20.01.2016 / 02:31
6
[ "$1" != "${1#/}" ] || return 1

Pode haver uma maneira melhor (é por isso que eu perguntei). Este código retira qualquer% de/ em $1 e verifica se o resultado não é igual ao $1 em si.

    
por 20.01.2016 / 02:06
3

A correspondência de padrões é feita com instruções case em todos os shells parecidos com Bourne.

is_absolute() {
  case "$1" in
    ///* | //) true;;
          //*) false;; # on some systems, //foo is special and is
                       # not an absolute path. // alone is /
           /*) true;;
            *) false
  esac
}

Remova as duas primeiras entradas nos sistemas que não tratam //foo especialmente.

    
por 20.01.2016 / 10:22
2

Se por caminho absoluto você quer dizer que começa com / , e estamos falando de bash (como tag suggest):

$ var1='/tmp/foo'
$ var2='tmp/foo'

$ [[ "$var1" =~ ^/ ]] && echo yes || echo no
yes
$ [[ "$var2" =~ ^/ ]] && echo yes || echo no
no
    
por 20.01.2016 / 02:28
2

Um caminho absoluto seria

  • comece com /
  • não contém /../ ou /./
  • não começa com ../ ou ./
  • não termina com /.. ou /.

para que você possa fazer isso (portável) com uma declaração de caso:

    case "x$1" in
    (x*/..|x*/../*|x../*|x*/.|x*/./*|x./*)
        rc=1
        ;;
    (x/*)
        rc=0
        ;;
    (*)
        rc=1
        ;;
    esac
    return $rc

Isso exclui intencionalmente coisas como

/../../../foo/../../../bar

que uma interpretação ingênua de "barra oblíqua" permite.

Para uma definição concisa de caminho absoluto , consulte realpath no POSIX.

    
por 20.01.2016 / 02:20
1

POSIX define caminho absoluto como um nome de caminho que começa com um único ou mais de dois / .

Existe um utilitário chamado pathchk para verificar o nome do caminho, para que você possa fazer:

[ -z "${1%%/*}" ] && pathchk -pP "$1"

-p informa pathchk para executar a verificação do caminho que:

-P protege você de qualquer componente de caminho que comece com - e um caminho vazio.

    
por 20.01.2016 / 02:49
1

Basta verificar o primeiro caractere da string usando a sintaxe de substring:

[[ ${var:0:1} = / ]] || return 1
    
por 20.01.2016 / 06:38