Kabuk betiğinde bir dosyanın olup olmadığını kontrol etme


175

Belirli bir dosyanın archived_sensor_data.jsonvar olup olmadığını kontrol eden bir kabuk betiği yazmak istiyorum , varsa ve siler. Aşağıdaki http://www.cyberciti.biz/tips/find-out-if-file-exists-with-conditional-expressions.html , ben aşağıdaki denedim:

[-e archived_sensor_data.json] && rm archived_sensor_data.json

Ancak, bu bir hata verir

[-e: command not found

komutunu test_controllerkullanarak ortaya çıkan komut dosyasını çalıştırmayı denediğimde ./test_controller. Kodda yanlış olan ne?



2
Açılış köşeli ayraç "[" ile seçenek "-e" arasında dosya adı ile kapanış köşeli ayraç "]" ile aynı veya daha fazla boşluk ayarlamanız gerekir
Konstantin Yaniv

Yanıtlar:


350

Köşeli ayraç ile aşağıdakiler arasında gerekli bir boşluk eksik -e:

#!/bin/bash
if [ -e x.txt ]
then
    echo "ok"
else
    echo "nok"
fi

12
Son olarak, iki boşluk, açıklık kare dirsek ardına ve kapatma bir önce bir eklendi: [ -e archived_sensor_data.json ] && rm archived_sensor_data.json. Senaryo şimdi çalışıyor gibi görünüyor.
Kurt Peek

3
Bu, if [ -e "$1" ](dosyaadı giriş argümanı) kullanılarak da çalışır .
Edward

2
Buradaki temel fark, "kabuk" komut dosyası yerine "bash" komut dizisini kullanmanızdır. Eklediğiniz ilk satırın #! / Bin / bash olduğuna dikkat edin, bu nedenle makineye sh yerine "bash" kullanmasını söylersiniz. Sh bu argümanı "-e" olarak tanımıyor
Nick Cuevas

29

İşte alternatif bir yöntem ls:

(ls x.txt && echo yes) || echo no

Eğer herhangi bir çıktıyı gizlemek isterseniz lssadece evet ya da hayır görmeleri için, yönlendirme stdoutve stderrhiç /dev/null:

(ls x.txt >> /dev/null 2>&1 && echo yes) || echo no

1
Bu kod şu anlama gelir: " lsbaşarılı olursa , böyle bir dosya vardır, aksi takdirde hiçbiri yoktur". lsBaşarısız olursa , dosyanın eksik olduğu anlamına gelmez. Başka bir hata olabilir. Örneğin, kök dizininde bir dosya oluşturun ve lsnormal kullanıcı altında yapmaya çalışın . Başarısız olur Permission denied, ki bu dosya mevcut olmayan bir eşdeğer değildir.
Tigran

9

Çözüm önerimin arka planı, ilk işinin ikinci haftasına kadar bir yapı sunucusu temizliğini silen bir arkadaşının hikayesidir. Yani temel görev bir dosyanın var olup olmadığını anlamak ve eğer varsa onu silelim. Ama bu nehirde birkaç hain akıntı var:

  • Her şey bir dosya.

  • Komut dosyalarının yalnızca genel görevleri çözmeleri durumunda gerçek gücü vardır

  • Genel olarak değişkenler kullanıyoruz

  • Manuel müdahaleyi önlemek için genellikle komut dosyalarında -f kuvvetini kullanırız

  • Ve aşk -r özyinelemeli, yarattığımız, kopyaladığımız ve imha ettiğimizden emin olmak için.

Aşağıdaki senaryoyu düşünün:

Silmek istediğimiz dosyaya sahibiz: filesexists.json

Bu dosya adı bir değişkende saklanır

<host>:~/Documents/thisfolderexists filevariable="filesexists.json"

Ayrıca, işleri gerçekten esnek hale getirmek için bir yol değişkenine sahibiz

<host>:~/Documents/thisfolderexists pathtofile=".."

<host>:~/Documents/thisfolderexists ls $pathtofile

filesexists.json  history20170728  SE-Data-API.pem  thisfolderexists

Bakalım -ene gerekiyorsa yapsın. Dosyalar mevcut mu?

<host>:~/Documents/thisfolderexists [ -e $pathtofile/$filevariable ]; echo $?

0

Öyle. Sihirli.

Ancak, eğer dosya değişkeni yanlışlıkla nuffin 'olarak değerlendirilirse ne olur?

<host>:~/Documents/thisfolderexists filevariable=""

<host>:~/Documents/thisfolderexists [ -e $pathtofile/$filevariable ]; echo $?

0

Ne? Bir hatayla geri dönmesi gerekiyor ... Ve bu, tüm klasörün yanlışlıkla nasıl silindiği hikayenin başlangıcı.

Bir alternatif, özellikle bir 'dosya' olarak anladığımız şeyleri test etmek olabilir

<host>:~/Documents/thisfolderexists filevariable="filesexists.json"

<host>:~/Documents/thisfolderexists test -f $pathtofile/$filevariable; echo $?

0

Dosya var ...

<host>:~/Documents/thisfolderexists filevariable=""

<host>:~/Documents/thisfolderexists test -f $pathtofile/$filevariable; echo $?

1

Bu bir dosya değil ve belki de tüm dizini silmek istemiyoruz

man test şunları söylemek gerekir:

-b FILE

       FILE exists and is block special

-c FILE

       FILE exists and is character special

-d FILE

       FILE exists and is a directory

-e FILE

       FILE exists

-f FILE

       FILE exists and is a regular file

...

-h FILE

       FILE exists and is a symbolic link (same as -L)

4

Dahili olarak, rm komutu zaten dosya varlığını test etmelidir,
neden başka bir test ekleyelim? Sadece sorun

rm filename

ve orada olsun ya da olmasın bundan sonra gidecek.
Rm -f kullan, varolmayan dosyalar hakkında herhangi bir mesaj istememenizdir.

Dosya mevcut DEĞİLSE bazı işlemler yapmanız gerekiyorsa, bunu kendiniz test etmeniz gerekir. Örnek kodunuza dayanarak, bu örnekte durum böyle değildir.


1
Bu aslında rm komutu için oldukça geçerli bir cevaptır. Diğer komutlar için -e ile test etmeyi öneririm.
warhansen

Ancak sorunun sorduğu şey bu değil.
Boya

1
“... ve (eğer öyleyse ... ... siler” kısmı dahil) tüm soruyu okursanız, sorunun sorduğu soru budur .
TG

1

NFS kullanıyorsanız, "test" daha iyi bir çözümdür, çünkü NFS'nizin kapanması durumunda zaman aşımı ekleyebilirsiniz:

time timeout 3 test -f 
/nfs/my_nfs_is_currently_down
real    0m3.004s <<== timeout is taken into account
user    0m0.001s
sys     0m0.004s
echo $?
124   <= 124 means the timeout has been reached

Bir "[-e my_file]" yapısı NFS tekrar işlevsel olana kadar donacaktır:

if [ -e /nfs/my_nfs_is_currently_down ]; then echo "ok" else echo "ko" ; fi

<no answer from the system, my session is "frozen">

testve [eşanlamlıdır. Sen kullanabilirsiniz timeoutile [sıra ve testayrıca NFS askıda kalır donar.
diğer adam
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.