Estrutura Variável do script shell

1

Como posso criar uma variável com um formato de nome de arquivo como:

Padrão FileName: SnapshotIR__somenumber.csv

Eu tentei algo como:

TODAY=$(date +"%m%d%Y")    
SNAPSHOT = $(SnapshotIR$TODAY*.csv)

Eu recebo um erro como:

test.sh: line 2: SnapshotIR02122013_2239.csv: command not found
test.sh: line 2: SNAPSHOT: command not found

então, quando eu quiser usar com

if [ -f SnapshotIR$TODAY*.csv]  -> works 
if [ -f ${SNAPSHOT} ]           -> does not work (I get the above error)
    
por Swagatika 12.02.2013 / 10:24

3 respostas

1

Quando você usa $() shell executará o conteúdo dentro de chaves como comando.
Você não tem permissão para usar espaços antes / depois do símbolo = .

Então seu comando será como

SNAPSHOT=SnapshotIR$TODAY*.csv

ou

SNAPSHOT=SnapshotIR${TODAY}*.csv

ps. Se você precisar fazer algumas operações com esses arquivos na próxima etapa, é melhor usar for cycle like

for file in SnapshotIR${TODAY}*.csv ; do smth ; done

porque, caso você tenha vários arquivos correspondentes ao seu padrão, [ -f ${SNAPSHOT} ] contruction retornará um erro como:

[ -f f* ] && echo ok
-bash: [: filename: binary operator expected
    
por 12.02.2013 / 10:52
2

Não use espaços em torno de = quando atribuindo variáveis .

Além disso, não creio que você queira incluir o que SNAPSHOT está atribuído em $( ) quando tentar executá-lo como um comando.

Em uma nota lateral, considere diminuir suas variáveis .

Então, o que você quer pode ser

today=$(date +"%m%d%Y")    
snapshot=SnapshotIR$today

if [ -f ${snapshot}*.csv ]
    
por 12.02.2013 / 10:37
2
SNAPSHOT = $(SnapshotIR$TODAY*.csv)

Você não pode ter um espaço nas atribuições. Além disso, $(…) é uma substituição de comando : esta linha tenta executar SnapshotIR02122013_2239.csv como um programa.

No bash, ksh ou zsh, defina SNAPSHOT como uma matriz contendo a lista de nomes de arquivos correspondentes.

SNAPSHOT=("SnapshotIR$TODAY"*.csv)

Se não houver nenhum arquivo correspondente, o padrão não será expandido. No bash ou zsh, defina a opção nullglob para obter uma matriz vazia. Em ksh, coloque ~(N) no início do padrão (ou seja, SNAPSHOT=(~(N)"SnapshotIR$TODAY"*.csv) ). Você pode então testar se havia algum arquivo correspondente testando o tamanho do array.

shopt -s nullglob
SNAPSHOT=("SnapshotIR$TODAY"*.csv)
if [ ${#SNAPSHOT} -eq 0 ]; then
  echo 1>&2 "No snapshot file for $TODAY"
  exit 2
elif [ ${#SNAPSHOT} -gt 1 ]; then
  echo 1>&2 "Multiple snapshot files for $TODAY, I don't know which one to pick"
  exit 2
fi
echo "The snapshot file is ${SNAPSHOT[0]}"

Em shells sem arrays, você pode usar uma função que receba a lista de correspondências e conte-as. Se não houver correspondência, a função recebe o padrão não expandido.

set_snapshot () {
  if [ $# -gt 1 ]; then
    echo 1>&2 "Multiple snapshot files for $TODAY, I don't know which one to pick"
    exit 2
  elif [ -e "$1" ]; then
     SNAPSHOT=$1
  else
    echo 1>&2 "No snapshot file for $TODAY"
    exit 2
  fi
}
set_snapshot "SnapshotIR$TODAY"*.csv
echo "The snapshot file is $SNAPSHOT"

(Observe que usar [ -e "$1" ] para testar se o padrão não foi expandido falha em casos patológicos, como [0-9] quando não há arquivo cujo nome é um único dígito, mas há um arquivo com o nome de 5 caracteres [0-9] . Isso não pode acontecer com apenas * ou ? metacaracteres, uma vez que eles se correspondem.)

A abordagem a seguir funciona até certo ponto:

SNAPSHOT=SnapshotIR$TODAY"*.csv
if [ -e $SNAPSHOT ]; then …

Como a expansão $SNAPSHOT não é citada, ela é tratada como uma lista separada por espaço em branco de padrões de curinga, o que é aceitável aqui. No entanto, se houver mais de um arquivo correspondente, as correspondências serão vistas como argumentos separados pelo comando [ e isso causará um erro de sintaxe. (Com nomes de arquivos especialmente criados, pode até causar um resultado errado.) Então, eu não recomendo essa abordagem, é muito frágil.

    
por 13.02.2013 / 01:47