web-dev-qa-db-fra.com

bash: interpréter la variable chaîne comme nom / chemin de fichier

Mon script bash reçoit un nom de fichier (ou un chemin relatif) sous forme de chaîne, mais doit ensuite lire à partir de ce fichier. Je ne peux lire à partir d'un nom de fichier que si je le déclare comme littéral directement dans le script (sans guillemets) ... ce qui est impossible pour les arguments car ce sont implicitement des chaînes pour commencer. Observer:

a="~/test.txt"
#Look for it
if [[ -a $a ]] ; then
    echo "A Found it"
else
    echo "A Error"
fi
#Try to use it
while read line; do
    echo $line
done < $a

b='~/test.txt'
#Look for it
if [[ -a $b ]] ; then
    echo "B Found it"
else
    echo "B Error"
fi
#Try to use it
while read line; do
    echo $line
done < $b

c=~/test.txt
#Look for it
if [[ -a $c ]] ; then
    echo "C Found it"
else
    echo "C Error"
fi
#Try to use it
while read line; do
    echo $line
done < $c

RENDEMENTS:

A Error
./test.sh: line 10: ~/test.txt: No such file or directory
B Error
./test: line 12: ~/test.txt: No such file or directory
C Found it
Hello

Comme indiqué ci-dessus, je ne peux pas passer un argument de ligne de commande aux routines ci-dessus car j'obtiens le même comportement que j'obtiens sur les chaînes citées.

17
Keith Wiley

Cela fait partie des règles de ~ - expansion. Il est clairement indiqué dans le manuel de Bash que cette extension n'est pas effectuée lorsque le ~ Est cité.

Solution de contournement 1

Ne citez pas le ~.

file=~/path/to/file

Si vous devez citer le reste du nom de fichier:

file=~/"path with spaces/to/file"

(Ceci est parfaitement légal dans une coque de jardin.)

Solution de contournement 2

Utilisez $HOME Au lieu de ~.

file="$HOME/path/to/file"

BTW: types de variables Shell

Vous semblez un peu confus quant aux types de variables Shell.

Tout est une chaîne.

Répétez jusqu'à ce qu'il s'enfonce: Tout est une chaîne. (Sauf les entiers, mais ce sont surtout des hacks au-dessus des chaînes AFAIK. Et des tableaux, mais ce sont des tableaux de chaînes .)

Il s'agit d'une chaîne Shell: "foo". "42" Aussi. 42 Aussi. Il en va de même pour foo. Si vous n'avez pas besoin de citer des choses, il est raisonnable de ne pas le faire; qui veut taper "ls" "-la" "some/dir"?

33
michaelb958