2016-04-11 20 views
2

Halihazırda bazı bash komut dosyalarının öğrenilmesi ve belirli bir dizindeki tüm dosyaların listelenmesi ve bunların bir dosya veya dizin olup olmadığının belirtilmesiyle ilgili bir sorunun bulunması. Sorun şu ki, sadece geçerli dizinimi almam ya da bir dizin belirtmek gerekirse, bunun bir dizin olduğunu söyleyebiliriz./home/user/shell_scripts geri dönecektir shell_scipts, içinde bulunan dosyalar yerine bir dizindir. Bu defa ne var:Belirli bir dizindeki dosyaları listelemek için Kabuk Betiği ve bunlar dosya veya dizinlerse

dir=$dir 
for file in $dir; do 
    if [[ -d $file ]]; then 
     echo "$file is a directory" 
    if [[ -f $file ]]; then 
     echo "$file is a regular file" 
    fi 
done 

cevap

2

Satır:

for file in $dir; do 

, $dir ürününü yalnızca tek bir dizin dizgisine genişletecektir. Yapmanız gereken şey, dizindeki dosyaların bir listesine genişletmektir. Aşağıdaki kullanarak yapabilirsiniz:

for file in "${dir}/"* ; do 

Bu, geçerli dizinin bir isim okunur listeye "${dir}/"* bölümünü genişleyecektir. Biffen'in işaret ettiği gibi, bu dosya dosyalarının herhangi biri beyaz boşluk içeriyorsa, dosya listesinin file numaralı dosyada bölünmüş kısmi dosya adları ile sona ermesini garanti etmelidir.

dir'daki dizinlere yeniden girmek istiyorsanız, find'u kullanmak daha iyi bir yaklaşım olabilir. Basitçe kullanın:

for file in $(find ${dir}); do 

Not kadar basit iken, bu irade onları boşluk olan değil sap dosyaları veya dizinleri. Bu nedenle, döngüyü düşürmek ve çıktıyı tek seferde üretmek cazip olurdu. Bu, istediğinizden biraz farklı olabilir, ancak özellikle çok sayıda dosyada okunması ve daha verimli olması daha olasıdır.

find ${dir} -maxdepth 1 -type d 

ve dosyaları listelemek için: Örneğin tüm dizinleri listelemek için

find ${dir} -maxdepth 1 -type f 

aşağıdaki dizinlere yineleme istiyorsanız, o zaman -maxdepth 1

+0

Gerçekten çok fazla dosya varsa, bu komut kırılabilir (komut satırı çok uzun). – user1934428

+0

Evet, her ne kadar bu yaklaşımı çok sayıda dosya (> 10^5) için defalarca kullandım ve bir sorunum olmasa da, _possible_. 'For'/'do' /' done' yaklaşımını atlatmaya ve eğer mümkünse 'ls' ya da' find' komutunu doğrudan kullanabilmeyi isterdim. OP'ler sorusu. Buna göre güncellenir. –

+0

Bu, boşluk veya başka özel karakterler içeren dosya isimleriyle iyi çalışmaz. – Biffen

0
for file in $(ls $dir) 
do 
    [ -f $file ] && echo "$file is File" 
    [ -d $file ] && echo "$file is Directory" 
done 

veya değiştirme

$(ls $dir) 

ile

`ls $` 
+0

Bu, boşluk veya başka özel karakterler içeren dosya isimleriyle iyi çalışmaz. Ve ne yapmalıyım? – Biffen

1
ls -F ~ | \ 
sed 's#.*/$#/& is a Directory#;t quit;s#.*#/& is a File#;:quit;s/[*/=>@|]//' 

kaldırmak -F "classify" anahtarı, bir dosya bir dizin ise "/" ekler. Sed kodu istenen mesajı yazdırır, ardından son eki kaldırır.

+1

Bu, adlarında yeni satırların bulunduğu dosyalarla çalışmaz. – Biffen

+1

Teşekkürler @Biffen, bu korkunç, yeni satırlarla dosya isimleri bir _thing_? Sadece şimdi onlara baktım. Sadece bir tane yaptı. Sadece yukarıdaki ** sed ** kodunu test ettik - başarısız oldu. Tamam, ama kim bile orada yeni hatlar var, bu şeyin tarihi nedir? 'Nasıl' olurum ve 'neden' diye sorarım… – agc

+1

'Neden olmasın' haricinde 'neden?' Diye cevaplayamıyorum. ;) – Biffen

2

Bu globbing için iyi bir kullanımıdır:

for file in "$dir/"* 
do 
    [[ -d "$file" ]] && echo "$file is a directory" 
    [[ -f "$file" ]] && echo "$file is a regular file" 
done 

Bu $dir dosyaları Boşluk, yıldız ve hatta yenisatırlar olarak adlarında özel karakterler olsa bile çalışacaktır.

Ayrıca değişkenlerin alıntılanması gerektiğini de unutmayın ("$file").Ancak *, alıntılanmamalıdır. Ve hiçbir şey yapmadığı için dir=$dir'u kaldırdım ($dir özel karakterler içeriyorsa kırılma dışında).