Variablen von der untergeordneten Shell in die übergeordnete Shell ausdrucken

Variablen von der untergeordneten Shell in die übergeordnete Shell ausdrucken

Bin ganz neu bei Bash und ziemlich verwirrt über lokale/globale Variablen/Subshells. Ich bin nicht sicher, warum die geänderten Variablen am Ende der Funktion nicht ausgedruckt werden – ich versuche, am Ende der Datei eine endgültige Zeilenanzahl und Dateianzahl auszudrucken, aber wenn ich das tue, wird nur 0 ausgedruckt, weil es lokale Variablen sind. Gibt es eine Möglichkeit, die geänderten Werte auszudrucken?

count=0
files=0
find . -type f | while IFC= read -r file;
do
   let files=files+1
   wc -l $file
   count=$(($count+$(wc -l < $file)))
   echo "total lines $count ; total files $files"
done
echo $files $count
exit 0

Antwort1

Ja. Aber es ist absolut nicht intuitiv. So funktioniert es beispielsweise:

#!/bin/bash
count=0
files=0
while IFS= read -r file;
do
   let files=files+1
   wc -l $file
   count=$(($count+$(wc -l < $file)))
   echo "total lines $count ; total files $files"
done < <(find . -type f )
echo "$files $count"
exit 0

Das <(command)Konstrukt heißt"Prozesssubstitution"und ermöglicht Ihnen, die Ausgabe eines Befehls als „Datei“ zu behandeln. Wenn Sie sie auf diese Weise in die Schleife einspeisen, funktioniert Ihr Skript wie erwartet.

Das Problem liegt in Ihrer Verwendung der Pipe ( |), die dazu führt, dass die While-Schleife in einer separaten Subshell ausgeführt wird, die keine Variablen außerhalb davon ändern kann.

In Shells, die diese Funktion nicht unterstützen <(), können Sie den bzw. die Befehle rechts von der Pipe in einer Subshell ausführen und das abschließende Echo in diese Subshell einbinden:

#!/bin/bash
files=0
find . -type f | {
    while IFC= read -r file;
    do
        let files=files+1
        wc -l $file
        count=$(($count+$(wc -l < $file)))
        echo "total lines $count ; total files $files"
    done
    echo "$files $count"
}

exit 0

verwandte Informationen