Döngü çıkışı için borular yerel değişken modifikasyonunu önler


11

Ben argüman olarak, bir dizi dosya ve / veya dizin alır basit bir bash işlevi yazmaya çalışıyorum. Olması gerekiyor:

  1. Dosya adlarını tam olarak nitelendirin.
  2. Onları sıralayın.
  3. Kopyaları kaldırın.
  4. Gerçekten var olan her şeyi yazdırın.
  5. Varolmayan dosyaların sayısını döndürür.

Neredeyse istediğimi yapan bir senaryom var, ama sıralama düşer. Komut dosyasının durduğu haliyle dönüş değeri doğru, ancak çıktı (sıralanmamış ve yineleniyor) değil. | sort -uBelirtildiği gibi ifadeyi kaldırırsam, çıkış doğrudur ancak dönüş değeri her zaman doğrudur 0.

NB Sorunu çözmek için daha basit çözümler bekliyoruz ama soru gerçekten neden bu kodda meydana geliyor. Yani, neden borunun eklenmesi betiğin değişkeni artırdığını gösteriyor r?

İşte senaryo:

function uniqfile
{
    local r=0 

    for arg in "$@"
    do  
        readlink -e "$arg" || (( ++r ))

    done #| sort -u    ## remove that comment

    return $r
}

Sadece küçük bir gözlem. Sen azaltabilir for arg in "$@"için for arg. "Eğer 'KELİMELERDE ...' mevcut değilse, "in" $ @ "" olduğu varsayılır. " - yardım
manatwork

Yanıtlar:


15

Bu, bu özellik nedeniyle iyi bilinen bir bash tuzağıdır :

Bir boru hattındaki her komut ayrı bir işlem olarak yürütülür (yani, alt kabukta).

değiştirilmiş değişkenlerin alt kabukta yerel olması ve üst öğede bir kez görünmemesi için.

Bundan kaçınmak için, bir işlem değişikliği ile boru hattından kaçınmak için kodunuzu yeniden yazın:

 for arg in "$@"
    do  
        readlink -e "$arg" || (( ++r ))

    done > >(sort -u)

Teşekkür ederim. Bu harika. Acaba bana yapının adını söyleyebilir misin >(..command..)? Ben düşünüyorum ben nasıl çalıştığını biliyorum ama bazı ek okumalar yapmaya gerektiğini hissediyorum.
tjm

2
@tjm: buna işlem ikamesi
enzotib 30:11


Süreç ikamesi , bir komutun girişinin veya çıkışının bir dosya olarak görünmesini sağlayan süreçler arası iletişim biçimidir. Komut, normalde bir dosya adının olacağı yerde , komut kabuğuyla değiştirilir. Bu, normalde yalnızca dosyaları kabul eden programların doğrudan başka bir programdan okumasını veya başka bir programa yazmasını sağlar.
nobar

3

| sort -uYukarıdaki bit (döngü için bütün böylece) bir alt süreç içinde çalıştırmak için kuvvetler (bash içine yönlendirmek için bir 'STDOUT' ihtiyacı sort'STDIN'. (Internet düşünüyor kshve bashilk veya son biraz farklı .. Bu durumda idare dizisi komut alt kabuk içine konur?)

Bu iş parçacığı benzer bir sorunun üstesinden geliyor ve sonunda düzgün bir çözümü var: http://ubuntuforums.org/showthread.php?t=312017

alıntı
    #!/bin/bash
    exec 3< <(du | sort -n)  

    n=0
    while read size dir; do
      [ $size -gt 1000 ] && ((n++))
    done <&3
    exec 3<&-

    echo "Found $n too big files"
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.