Definir uma variável como ~ / diretório não expande

6

Estou tentando configurar um script de backup simples com tar, como você pode ver abaixo:

#!/bin/bash
TIME='date +%F_%H-%M'
FILENAME=backup-$TIME.tar.gz
SRCDIR="~/PI/tutos/* ~/scripts/*"
DESTDIR=/media/sf_ubuntuSharedFolder/backups
tar cvpzf $FILENAME $SRCDIR

No entanto, o uso de $ SRCDIR causa um erro de tar que eu não tenho se eu apenas expandi-lo sozinho.

alex@ALeX-VirtualBox:~$ save
tar: ~/PI/tutos/*: Cannot stat: No such file or directory
tar: ~/scripts/*: Cannot stat: No such file or directory

O que há de errado em usar uma variável shell? Caso contrário, como posso passar uma lista de pastas para tar em uma única linha?

    
por AALLeeXX 30.07.2016 / 11:08

1 resposta

10

O problema é que ~ -expansion não é executada na expansão da variável (quando você se refere a esse $SRCDIR não-citado) nem entre aspas duplas (quando você atribui essa variável SRCDIR ).

Ao deixar $SRCDIR sem aspas, você está chamando o operador split + glob. Essa é a string que é armazenada no escalar $SRCDIR variable ( ~/PI/tutos/* ~/scripts/* ) é primeiro dividida de acordo com $IFS (espaços em branco por padrão), e então cada palavra sofre globbing, ou seja, são tratados como padrões que se expandem para o lista de arquivos correspondentes.

Como ~ não está expandido para o seu diretório home, esse ~ é tratado apenas como qualquer outro caractere, portanto, ele está apenas procurando por arquivos no diretório ~/PI/tutos , em que ~ seria um diretório em o diretório atual, que no seu caso não existe.

O melhor aqui seria tornar $SRCDIR uma matriz e ter as globs expandidas no momento da atribuição:

SRCDIR=(~/PI/tutos/* ~/scripts/*) # ~ and globs expanded at this point
tar cvpzf "$FILENAME" "${SRCDIR[@]}"

Note que aplicar o operador split + glob em $FILENAME não faz sentido, então estamos desabilitando-o citando $FILENAME .

Observe que, se ~/PI/tutos/* não corresponder, será deixado como está, portanto, você ainda receberá um erro de tar . Para evitar isso, você poderia fazer:

shopt -s nullglob # remove non-matching globs
SRCDIR=(~/PI/tutos/* ~/scripts/*)
if ((${#SRCDIR[@]} != 0)); then
  tar cvpzf "$FILENAME" "${SRCDIR[@]}"
fi

Você pode ficar tentado a fazer:

SRCDIR="$HOME/PI/tutos/* $HOME/scripts/*"
tar cvpzf "$FILENAME" $SRCDIR

Como as variáveis (como $HOME ) são expandidas entre aspas duplas, mas aconselhamos que não funcione corretamente se $HOME contiver caracteres glob ou caracteres de $IFS .

~ s são expandidos em atribuições de variáveis quando não estão entre aspas e quando no início ou no seguimento : (é assim que funciona em atribuições de variáveis como $PATH , $LD_LIBRARY_PATH ... como PATH=~/bin:~/sbin ). Então você pode ser tentado a fazer:

SRCDIR=~/PI/tutos/*:~/scripts/* # ~ (not globs) expanded here
IFS=:
tar cvpzf "$FILENAME" $SRCDIR

Mas é o mesmo acima, que não funcionará corretamente se $HOME contiver $IFS caracteres (desta vez : , muito improvável, pois /etc/passwd que define seu diretório inicial é uma tabela separada por dois-pontos ) ou caracteres glob.

    
por 30.07.2016 / 11:41