Perpipaan untuk keluaran loop mencegah modifikasi variabel lokal


11

Saya mencoba menulis fungsi bash sederhana yang mengambil, sebagai argumennya, sejumlah file dan / atau direktori. Itu harus:

  1. Sepenuhnya memenuhi syarat nama file.
  2. Sortir mereka.
  3. Hapus duplikat.
  4. Cetak semua yang benar-benar ada.
  5. Kembalikan jumlah file yang tidak ada.

Saya memiliki skrip yang hampir melakukan apa yang saya inginkan, tetapi jatuh pada penyortiran. Nilai kembalinya skrip sebagaimana mestinya benar, tetapi hasilnya tidak (tidak disortir dan digandakan). Jika saya batalkan komentar | sort -useperti yang ditunjukkan, output sudah benar tetapi nilai kembali selalu 0.

NB solusi yang lebih sederhana untuk menyelesaikan masalah ini disambut baik tetapi pertanyaannya adalah tentang mengapa ini terjadi pada kode yang saya miliki. Artinya, mengapa menambahkan pipa sepertinya menghentikan skrip yang menambah variabel r?

Ini skripnya:

function uniqfile
{
    local r=0 

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

    done #| sort -u    ## remove that comment

    return $r
}

Hanya pengamatan kecil. Anda dapat mengurangi for arg in "$@"menjadi for arg. "Jika 'dalam KATA ...;' tidak ada, maka 'dalam "$ @"' diasumsikan. " - help for
manatwork

Jawaban:


15

Ini adalah perangkap bash yang terkenal, karena fitur ini :

Setiap perintah dalam sebuah pipa dieksekusi sebagai proses terpisah (yaitu, dalam subkulit).

sehingga variabel yang dimodifikasi adalah lokal ke subkulit, dan tidak terlihat sekali kembali di induk.

Untuk menghindari itu, ulangi kode Anda untuk menghindari pipa, dengan substitusi proses:

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

    done > >(sort -u)

Terima kasih. Itu hebat. Saya ingin tahu apakah Anda dapat memberi tahu saya nama >(..command..)konstruknya. Saya rasa saya tahu cara kerjanya tetapi saya merasa harus melakukan bacaan lebih lanjut.
tjm

2
@ tjm: itu disebut proses substitusi
enzotib

Substitusi proses di Bash memiliki banyak bentuk: tldp.org/LDP/abs/html/process-sub.html
slm

Substitusi proses adalah bentuk komunikasi antar-proses yang memungkinkan input atau output dari suatu perintah muncul sebagai file. Perintah ini diganti in-line, di mana nama file biasanya muncul , oleh shell perintah. Ini memungkinkan program yang biasanya hanya menerima file untuk langsung membaca atau menulis ke program lain.
nobar

3

The | sort -upasukan bit sebelumnya (sehingga seluruh untuk loop) untuk menjalankan dalam sub-proses (bash membutuhkan 'STDOUT' untuk mengarahkan ke sort'STDIN'. (Internet tampaknya berpikir kshdan bashmenangani kasus ini sedikit berbeda .. pertama atau terakhir perintah dalam urutan pipa akan dimasukkan ke dalam subkulit?)

Utas ini membahas masalah serupa, dan memiliki solusi rapi di bagian akhir: http://ubuntuforums.org/showthread.php?t=312017

kutipan
    #!/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"
Dengan menggunakan situs kami, Anda mengakui telah membaca dan memahami Kebijakan Cookie dan Kebijakan Privasi kami.
Licensed under cc by-sa 3.0 with attribution required.