2010-10-25 19 views
26

Hızlı Amaç:Bash için-Loop Dizinlerinin

$ ls src 
file1 file2 dir1 dir2 dir3 

Senaryo:

#!/bin/bash 

for i in src/* ; do 
    if [ -d "$i" ]; then 
    echo "$i" 
    fi 
done 

Çıktı:

dir1 
dir2 
dir3 
: Ancak

src/dir1 
src/dir2 
src/dir3 

, bunu okumak istiyorum

Şimdi, "src /" yi kaldırmak için çıktıyı kaldırabileceğimin farkındayım, ancak bunun hakkında daha iyi bir yol olup olmadığını merak ediyorum. Bunun yerine bir find + while-loop kullanıyor olabilirsiniz.

cevap

16

yerine echo hattı için bunu yapın:

echo $(basename "$i") 
+0

yerine * birdizin * ding * Eğer * basename okumak için yazı güncelledik bkz ding, ding DOĞRU !!! : D Teşekkürler, cevabınızı kabul edeceğim – BassKozz

+0

Bu nugget'i bir O'Rielly kitabından sadece 2 gün önce öğrendim. Yıllar önce bilebilirsem, saatlerce süren şapcılığı kurtarırdım. – Synesso

3

kullanın basename olarak:

if [ -d "$i" ]; then 
    basename "$i" 
fi 
10

harici sürecini bölmek gerek yoktur:

echo "${i##*/}" 

O “kaldır kullanır En uzun eşleşen önek ”parameter expansion. */ desendir, bu nedenle dizenin başına kadar ve son eğik çizgi dahil olmak üzere her şeyi siler. $i değerinde eğik çizgi yoksa, "$i" ile aynıdır.

Bu özel parametre genişleme specified in POSIX ve orijinal Bourne kabuğunun miras bir parçasıdır. Tüm Bourne gibi kabuklar desteklenir (sh, kül, çizgi, Ksh, deneme, zsh, vs.). Zengin özelliklere sahip kabukların birçoğu (ör.ksh,bash ve zsh) dış işlemlere gerek duymadan daha fazla işleyebilecek başka genişletmelere sahiptir. Eğer komut başında cd yaparsanız komut çıktığında

8

, döndürülmesi gerekmektedir.

#!/bin/bash 

cd src 
for i in * ; do 
    if [ -d "$i" ]; then 
    echo "$i" 
    fi 
done 
+2

yapmalı… ama betiği çağırmak için '.' veya' source' komutunu kullanırsanız, olmaz. Daha ziyade 'pushd' ve' popd' kullanın. – Benoit