O comando [
é um comando e é analisado como qualquer outro comando. Isso significa que em:
[ "$path" == ?*"@"?*":"?* ]
O ?*"@"?*":"?*
é considerado como glob e, portanto, expande para a lista de arquivos no diretório atual que corresponde a esse padrão (assim como *.txt
expande para a lista de txt
arquivos no diretório atual). / p>
Mesmo se você escreveu:
[ "$path" == '?*@?*:?*' ]
para impedir a globbing, que não funcionaria como o operador ==
(versão não padrão de =
) do comando [
é apenas um operador de igualdade de cadeia, não um padrão correspondente.
Para fazer a correspondência de padrões, você pode usar o operador de correspondência de padrões ksh
-style [[ x = pattern ]]
, que bash
e zsh
também suportam:
path="user@host:/home/user"
if [[ "$path" = ?*@?*:* ]]; then
some code
fi
Ou, melhor ainda, use a construção POSIX / Bourne sh
case
:
case $path in
?*@?*:*) some code
esac
Dessa forma, você nem precisa ter o bash
instalado, você pode usar o padrão do seu sistema sh
para interpretar o seu script.
Observe que user@host:/home/user
também é um caminho local válido (tente mkdir -p user@host:/home/user
), embora com scp
seja necessário passá-lo como ./user@host:/home/user
para que não seja tratado como um caminho remoto. Então você pode querer refinar seu teste para:
case ${path%%@?*:*} in
(*/* | "$path" | "") echo not a remote path;;
(*) echo remote path;;
esac
Para que ./x@y:z
não seja tratado como um caminho remoto.
Ainda não é suficiente fazer o mesmo que scp
faz para decidir se um caminho é remoto ou não. Olhando para OpenSSH scp
code , um caminho é remoto se não Comece com :
e se ele contiver um :
sem /
à esquerda dele e que não esteja dentro de [...]
(para endereços IPv6 como [::1]
. Exceto que esses [...]
são apenas considerado na posição do host (no início ou após @
) Assim, por exemplo x:
, @:
são caminhos remotos (embora obviamente a parte do usuário e do host esteja vazia, isso provavelmente não funcionará corretamente) e user@[::1/64]:/x
( /
restante para o :
que não está entre [...]
) ou [foo@bar:/path
são caminhos locais (o :
está dentro de [...]
).
A correspondência com uma instrução POSIX case
seria impossível. Para corresponder a uma expressão regular, seria um pouco mais fácil com expressões regulares que suportam a pesquisa em torno de operadores como perl
. zsh
e ksh93
têm suporte para aqueles ( zsh
usando a biblioteca PCRE, ksh93
usando sua própria implementação).
-
zsh
:set -o rematchpcre remote='^(?!:)(?:(?!\[)[^/:]*@)?(?:\[(?:(?!]:)[^/])*\]|(?!\[)[^/:]*):' if [[ $path =~ $remote ]]; then some code fi
-
ksh93
:remote='(?P:^(?!:)(?:(?!\[)[^/:]*@)?(?:\[(?:(?!]:)[^/])*\]|(?!\[)[^/:]*):)' if [[ $path =~ $remote ]]; then some code fi
(Eu não ficaria surpreso se isso pudesse ser simplificado).