SORU
19 Kasım 2008, ÇARŞAMBA


Nasıl bash döngü listesinde boşluk kaçabilir miyim?

Belirli bir dizin ve tüm alt dizinleri (ama dosyaları değil) aracılığıyla döngüsü bash bir kabuk var. Bu sorun, dizin adları, boşluk içeren.

İşte benim test dizininin içeriği:

$ls -F test
Baltimore/  Cherry Hill/  Edison/  New York City/  Philadelphia/  cities.txt

Ve dizinleri döngüsü kodu:

for f in `find test/* -type d`; do
  echo $f
done

İşte çıkış:

test/Baltimore
test/Cherry
Hill
test/Edison 
test/New
York
City
test/Philadelphia

Cherry Hill ve New York 2 veya 3 ayrı girişler olarak kabul edilir.

Dosya alıntı, çok hoşuma çalıştı:

for f in `find test/* -type d | sed -e 's/^/\"/' | sed -e 's/$/\"/'`; do
  echo $f
done

ama sonuç çıkmadı.

Bunu yapmak için basit bir yolu olmalı.


Cevabını çok iyi. Ama bu daha karmaşık hale getirmek için - her zaman dizinler benim test rehberinde kayıtlı kullanmak istemiyorum. Bazen komut satırı yerine parametre olarak dizin adlarını geçmek istiyorum.

Charles ve EĞERLER ayarı öneri aşağıdaki ile geldi: aldım

dirlist="${@}"
(
  [[ -z "$dirlist" ]] && dirlist=`find test -mindepth 1 -type d` && IFS=$'\n'
  for d in $dirlist; do
    echo $d
  done
)

ve bu komut satırı argümanları eğer bu tartışmalar alıntı olsa bile () boşluk olmadığı sürece gayet güzel çalışıyor. Örneğin, bu gibi script arama: test.sh "Cherry Hill" "New York City" aşağıdaki çıktıyı üretir:

Cherry
Hill
New
York
City

CEVAP
19 Kasım 2008, ÇARŞAMBA


İlk olarak, böyle yapma. En iyi yaklaşım find -exec düzgün kullanmak için:

# this is safe
find test -type d -exec echo '{}'  

Diğer güvenli yaklaşım bu senin 20 ** destek bulmak gerekir ama BOŞ sonlandırılmış bir listesini kullanmak için:

# this is safe
while IFS= read -r -d '' n; do
  printf '%q\n' "$n"
done < <(find test -mindepth 1 -type d -print0)

Ayrıca bulmak bir dizi doldurmak ve o Dizideki bir sonraki geçirebilirsiniz:

# this is safe
declare -a myarray
while IFS= read -r -d '' n; do
  myarray =( "$n" )
done < <(find test -mindepth 1 -type d -print0)
printf '%q\n' "${myarray[@]}" # printf is an example; use it however you want

Eğer bulmuyor destek -print0, sonuç ortada güvensiz ... aşağıda değil gibi davranmak isterseniz dosya varsa da içeren yeni satır isimlerini (ki, Evet, yasaldır):

# this is unsafe
while IFS= read -r n; do
  printf '%q\n' "$n"
done < <(find test -mindepth 1 -type d)

Eğer bir değil mi kullanacak biri yukarıda, üçüncü bir yaklaşım (daha az verimli açısından hem zaman hem de bellek kullanımı gibi okur, tüm çıkış alt işlemi yapmadan önce kelime-bölme) kullanın IFS değişken olan değil içerir karakter. Genişletilmiş olmaktan dizeleri [], * ? gibi topak karakterler içeren önlemek için genelleme (set -f) kapatın:

# this is unsafe (but less unsafe than it would be without the following precautions)
(
 IFS=$'\n' # split only on newlines
 set -f    # disable globbing
 for n in $(find test -mindepth 1 -type d); do
   printf '%q\n' "$n"
 done
)

Son olarak, komut satırı parametresi durum için, eğer kabuk destekliyorsa (yani ksh, bash veya zsh) dizileri kullanarak olmalıdır:

# this is safe
for d in "$@"; do
  printf '%s\n' "$d"
done

ayrılık koruyacaktır. Bu alıntı ($@ yerine $*) önemli olduğunu unutmayın. Diziler şu ifadeler gibi, diğer şekillerde doldurulabilir

# this is safe
entries=( test/* )
for d in "${entries[@]}"; do
  printf '%s\n' "$d"
done

Bunu Paylaş:
  • Google+
  • E-Posta
Etiketler:

YORUMLAR

SPONSOR VİDEO

Rastgele Yazarlar

  • Dive In

    Dive In

    17 Temmuz 2013
  • ThePointblank

    ThePointblan

    18 Aralık 2006
  • JeezyVEVO

    JeezyVEVO

    12 Mayıs 2009