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
İ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

Nasıl Bash dize değişkenleri bitiştirm...
Nasıl ve bash ile bir dosya için hem s...
Nasıl Python listesinde bir öğenin yin...
Nasıl bir Bash değişken boşluk kırpmak...
Nasıl Bash komut dosyası için burada b...