2010-06-28 21 views
5

Bir BASH komut dosyasında, bir dosyanın var olup olmadığını algılamaya çalışıyorum. Dosya adı bir değişkendir, ancak -e komutu dosyayı algılayamayacak gibi görünüyor. Aşağıdaki kod her zaman verir "~/misc/görevler/drupal_backup.sh yok"Bash komut dosyası - bir değişkende dosya adını algılayamıyor

Öte yandan
filename="~/misc/tasks/drupal_backup.sh" 

if [ -e "$filename" ]; then 
    echo "$filename exists" 
else 
    echo "$filename does not exist" 
fi 

aşağıdaki kodu doğru dosyayı algılar:

if [ -e ~/misc/tasks/drupal_backup.sh ]; then 
    echo "$filename exists" 
else 
    echo "$filename does not exist" 
fi 

Bu neden olacaktır ? Dosya adı bir değişken içerdiğinde dosyayı nasıl algılayabilirim?

+1

Komut satırında kullanılmaması gereken komut satırı kolaylığını '~ 'olarak kabul ediyorum. –

cevap

7

Bu ilginç bir tanesi. ~ için $HOME'un değiştirilmesi, ödevin alıntıdan çıkarılması gibi çalışır.

Bu komut dosyasının en üstünde bir set -x koyarsanız, tırnak işareti içeren sürümün -e için verilen dosya olan ~/... olarak ayarlandığını görürsünüz. Tırnakları kaldırırsanız, dosya adı genişletilmiş /home/somebody/...'a ayarlanır. Yani ilk durumda, görüyorsunuz:

+ [ -e ~/... ] 

ve bunu sevmiyor. İkinci durumda, gördüğünüz:

+ [ -e /home/somebody/... ] 

ve çalışır. değişkene olmadan yaparsanız

, gördüğünüz:

+ [ -e /home/somebody/... ] 

ve evet, işe yarıyor. Soruşturmanın biraz sonra


, ben aslında bash onun açılımları gerçekleştirir sırası olduğunu gördük. bash adam sayfasından:

açılımları sırası şöyledir: ayracı genişletme, yaklaşık yorumlaması, parametre, değişken ve (soldan-sağa şekilde hazırlanacaktır) aritmetik genişleme ve komut ikamesi, kelime bölme ve yol adı genişleme. işe yaramıyor yüzden

, değişken yaklaşık yorumlaması sonra ikame edilir. Başka bir deyişle, bash'un ~'u genişletmek istediği noktada, bir tane yok. Değişken genişlemeden sonra sadece kelime ~/... olarak değişir ve bundan sonra tilde genişleme olmaz.

Bir şey olabilir yapmak için if deyimi değiştirmektir: iki kez $ dosya argümanı değerlendirecek

if [[ -e $(eval echo $filename) ]]; then 

Bu. İlk kez (eval ile), tilde genişleme fazı sırasında ~ olmayacaktır, ancak $filename, değişken genleşme fazı sırasında olarak değiştirilecektir.Daha sonra, ikinci değerlendirmede (if'un bir parçası olarak yapılmakta olan), ~, tilde genişleme aşamasında orada olacaktır.

Bunu .profile dosyamda denedim ve işe yarıyor gibi görünüyor, özel durumunuzu doğrulamanızı öneririz.

+0

Teşekkürler! Sadece ~ HOME ile değiştirerek mükemmel bir şekilde çalıştı. – thornate

+1

Hiçbir zaman "eval" kullanmamalısınız. '~', etkileşimli mod için güzel bir kısaltmadır, ancak tam olarak bu nedenle komut dosyalarında engellenmelidir. Birçok init betiği, [-r ~/.profile] && gibi bir şey içerir. ~/.profile' ve giriş dizini boşluk içeriyorsa, bunun çalışıp çalışmadığını bilmiyorum. Daha iyi $ HOME kullanmak ve tüm değişkenleri alıntılamaktır: 'filename =" $ HOME/misc/tasks/drupal_backup.sh "'. Bu durumda, alıntılama gerekli değildir, ancak bu zararlı değildir ve alıntıların neresinden ayrılabileceğinizi tam olarak bilemezseniz, her şeyi basitçe alıntılamak daha kolaydır. – Philipp

+0

@Phillipp, eğer bir meritokraside "asla değerlendirmemelisiniz" gibi bir battaniye ifadesi yapacaksanız, kendi ana dizininizle yedeklemeyi düşünmek isteyebilirsiniz :-) – paxdiablo

İlgili konular