So erstellen Sie einen rekursiven Funktionsaufruf in Unix

So erstellen Sie einen rekursiven Funktionsaufruf in Unix
#!/bin/sh
checking()
{
  cd "$1"
  for D in *;do
    if [ -d "$D" ]; then
      cd "$D"
      for d in *;do
        echo "$d"
        if [ -d "$d" ]
        then
           `checking() $d`
        fi
        if [ -f "$d" ]
        then
                file_name=`echo "$d" | cut -d'.' -f1`
                echo $file_name
                file_ext=$(echo $d |awk -F . '{if (NF>1) {print $NF}}')
                echo $file_ext
                if [ $file_ext = bin ]
                then
                        strings $d > $file_name.txt
                        mv $file_name.txt /somepath
                fi
        fi

      done
      cd ..

    fi
  done
}

a=$(pwd)
checking() $a

Ich konvertiere Binärdateien des Sitzungsprotokolls in Textdateien und speichere sie mithilfe der String-Funktion auf einem Pfad. Für jedes Verzeichnis funktioniert es einwandfrei, aber es prüft die Binärdateien nicht auf vorhandene Unterverzeichnisse.

Ich habe versucht, einen rekursiven Funktionsaufruf zu verwenden, aber dieser Aufruf wird nicht ausgelöst. Bitte helfen Sie

Antwort1

Mir fallen bei Ihrer Funktion ein paar Dinge auf:

  • Man wechselt in ein Verzeichnis, iteriert dann über die Dateien und macht dann beideswieder( cd; for d in *; do cd; for d in * ...). Dies scheint, als würde es bei einem rekursiven Durchlauf jede zweite Ebene des Verzeichnisbaums überspringen. Eine Iteration über die Dateien sollte ausreichen
  • Ich glaube nicht, dass Sie eine Subshell verwenden müssen, wenn Sie die Funktion rekursiv aufrufen (es gibt die Backtick-Befehlssubstitution in `checking() $d`). Das könnte nützlich sein, wenn Sie lokale Variablen für jede Instanz des Funktionsaufrufs benötigen, aber viele Shells können das direkt tun (mit localin Bash,anscheinend typesetin ksh93)
  • Und natürlich die Syntax zum Aufrufen einer Funktion: hi() { echo "hello $1"; }Wir führen sie wie jeden anderen Befehl aus, einfach mit hi "$name".
  • Wir können das streichen awkund die Shell verwendenParametererweiterungum die Dateierweiterung auszuwählen. (Überprüfen Sie jedoch den Grenzfall, wenn der Dateiname keinen Punkt enthält.) Oder verwenden Siecase "$f" in *.bin) ...

Hier ist eine recht einfache Funktion zum Durchlaufen eines Verzeichnisbaums:

#!/bin/sh

walk() {
        cd "$1"
        for f in *; do 
                if [ -d "$f" ] ; then
                        echo descending into "$f"...
                        walk "$f"
                else
                        ext=${f##*.}
                        if [ "$ext" = "bin" ] ; then
                                echo "found .bin file: $f"
                        fi
                fi

        done
        cd ..
}

walk .

(Beachten Sie jedoch, dass die cd "$dir"; ... ; cd ..Struktur Probleme verursachen kann, wenn jemand ein Verzeichnis genau in dem Moment verschiebt, in dem das Programm dieses Verzeichnis verarbeitet. Der ..Link würde sich ändern, und die Rückkehr darüber würde vom neuen Speicherort aus fortgesetzt, der möglicherweise sogar außerhalb des ursprünglichen Baums liegt. Wir könnten das umgehen, indem wir immer absolute Pfadnamen verwenden oder mit pushd/popd(in Bash) oder indem wir die gesamte Funktion oder Aufrufe davon in Subshells platzieren.)

verwandte Informationen