"Else", boş bir "then" cümlesi takip ettiğinde Bash sözdizimi hatası


35

Neden aşağıdaki betiği çalıştırmak değil, sözdizimi hatası veriyor else:

LOGS3_DIR=~/logs
if [ -d "$LOGS3_DIR" ]; then
 cd
 cd "$LOGS3_DIR"
 echo "$LOGS3_DIR"
 for filename in `find "." -mtime 1 -type f`
  do
  if lsof "$filename" > /dev/null
  then
    # file is open
  else
    echo "deleting $filename"
    rm "$filename"
  fi
 done
fi

Yanıtlar:


23

Çıktısında komut değiştirme kullanmayınfind . Burada her şey yapılabilir find:

find . -mtime 1 -type f ! -exec lsof -t {} \; -exec rm -f {} \; > /dev/null

Birkaç finduygulamada ( findnereden geldiği FreeBSD ve GNU dahil find) -deleteyerine kullanabilirsiniz -exec rm....

Hata almanın nedeni, bazı kabukları arasında ( thenve elsebu sözdiziminin nereden geldiği Bourne kabuğu ile başlayarak) arasında en az bir tane (ve bir yorum bir komut değildir) arasında bir komut bulunmamasıdır. Tamamen keyfi olduğunu ve bu mermilerin bunu yapmasının bir nedeni olmadığını unutmayın. yashve zshbu sınırlamaya sahip değilsiniz ( if false; then else echo x; five hatta if false; then else fionlarla iyi çalışabilirsiniz).

Diğerlerinin söylediği gibi :(veya for nothing in; do nothing; done) gibi bir noop komutunu kullanabilir veya mantığı !anahtar sözcükle (POSIX kabuklarında kullanılabilir, ancak Bourne kabuğunda kullanamazsınız) (bunun için kullanmanın :o kabukta yaygın olduğunu göreceksiniz ) kullanabilirsiniz. mkshve yashdestek olur if false; then () else echo x; fi(gelecekteki sürümlerde de değişebileceği için buna güvenmezdim).

Başka bir yaklaşım ise:

lsof... || {
  cmd1
  cmd2
}

tek fark bu olacak genel çıkış durumudur olsa lsofeğer lsofbaşarısız olur.


17
Bu, @ Acemi Kullanıcının denediği şeyi yapmanın çok daha iyi bir yolu olsa da, soruyu hiç yanıtlamıyor.
SeeJayBee

Her -execne kadar yararlı olsa da xargs, bazen bir kabuk halkasına ihtiyaç duyulur. Bu durumda bir while read namedöngü tercih edilen seçenektir (GNU ile bash'te her ikisi için de -0 seçeneğini kullanabilirsiniz; portatif olarak newline'dan vazgeçmeniz gerekir).
Jan Hudec

@ JanHudec, taşınabilir yollar var. -print0olduğu -exec printf '%s\0' {} +(ancak portably sen dikkate alınmasını istiyorsanız dışında o çıkışı ile baş edemez perl) ve ile find .//.ve bazı post-processing, sizin için yeni satır kaçabilir xargs. Bu bir değil unutmayın while read, bu kadar while IFS= read -r.
Stéphane Chazelas

@Chris, cevap kabul edildikten sonra asıl soruya bir cevap ekledim.
Stéphane Chazelas

90

Dosya açıksa, no-op yapmak istiyormuş gibi görünüyorsunuz :, bu nedenle null komutunda bir a eklemelisiniz bash:

if lsof "$filename" > /dev/null; then
  # file is open
  :
else
  printf 'deleting %s\n' "$filename"
  rm -- "$filename"
fi

Eğer kullanmıyorsanız :, bashsize kodu ayrıştırmak olamaz ve benzeri hata gösterecektir bash: syntax error near unexpected token 'else'.


asla yeni :değil ve bash-builtins'te listelenen ilk komuttur.
bolov

26

Başka bir alternatif: mantığınızı ters çevirin.

if ! lsof "$filename" >/dev/null;then
    echo "deleting $filename"
    rm "$filename"
fi

17

TL; DR

Diğer yanıtların hiçbiri, komutun neden bir sözdizimi hatası verdiğine dair orijinal sorunuza cevap vermiyor. Bu o zaman ve başka arasında eksik bir komuttan kaynaklanır .

Eksik Komuta

Orijinal kodunuz şuna benzer:

if lsof "$filename" > /dev/null
then
  # file is open
else
  echo "deleting $filename"
  rm "$filename"
fi

Sorun, o zaman ve diğer arasında bir yorumunuz olması , ancak yorumu bir komut olarak kabul etmiyor olmanızdır . Kısacası, (yapısal olarak konuşmakta olduğunuz) probleminizi aşağıdaki gibi yeniden yazabilirsiniz:

$ if true; then else echo; fi
bash: syntax error near unexpected token `else'

Bourne Builtin ile Sözdiziminizi Düzeltin

Daha önce fiili komutları yerleştirerek bu sorunu çözebilirsiniz başka , ama kendi başına bir açıklama yapmayacağım. Öyleyse, o zaman bölümü boş olamaz; Yer tutucu istiyorsanız, kolon yerleşimini kullanabilirsiniz . Örneğin:

$ if true; then :; else echo; fi

Basitçe o zaman ve başka: bölümlerin arasına yerleştirmek , yaşadığınız sözdizimi hatasını düzeltecektir.


1
Aynı zamanda en çok oylanan cevap olan Gnouc cevabı da asıl soruya değiniyor.
jlliagre

Sadece sözdizimi hatasını ele almak için cevap. FWIW, benzer bir hatayı satırın başındaki tek noktalı virgül ile yeniden oluşturabilirsiniz. Bu güçlü bir ipucu verecektir. $ ; -bash: syntax error near unexpected token ';'
Matthew Hannigan
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.