Pro-Linux.de

Pro-Linux

Pro-Linux Diskussions- und Hilfeforum
Aktuelle Zeit: 20. Nov 2018 8:41

Alle Zeiten sind UTC+01:00




Ein neues Thema erstellen  Auf das Thema antworten  [ 6 Beiträge ] 
Autor Nachricht
BeitragVerfasst: 25. Feb 2009 13:27 
Hi,

bin gerade dabei mich in Linux und Bash bzw. Shell Scripting einzuarbeiten. Mit anderen Worten: ein Shell Script-Anfänger.

Ich soll ein Script schreiben, welches mit Hilfe von Übergabeparametern ein Verzeichnis auf Dateien durchsucht. Sofern im selben Verzeichnis eine Datei mit dem selben Dateinamen, aber mit anderer Dateiendung vorhanden ist, sollen die zutreffenden Dateien kopiert werden.

Konkret sieht der Scriptaufruf so aus:
./script.sh <quellverzeichnis> <zielverzeichnis> <dateiendung1> <dateiendung2>
also z.B. ./script.sh /home/test/ /home/test/archiv/ md5 tgz

Beispieldateien im Verzeichnis /home/test/:
20090220_132010_blabla.tgz
20090220_132010_blabla.md5
20090221_151050_dumdidum.tgz
20000221_151050_dumdidum.md5
(Sofern zu einer .tgz-Datei eine zugehörige .md5-Datei existiert, sollen sowohl tgz und md5 kopiert werden)

Mein bisheriger Ansatz wie folgt:
Code:
#!/bin/bash

inputDir=$1
outputDir=$2
fileExt1=$3
fileExt2=$4

var1=&#40; `find $inputDir -name "*.$fileExt1" | sed "s/.$fileExt1//g;s/$inputDir//g"` &#41;    # sed benutzen, um bei der Datei-Trefferliste jeweils die Dateiendung und den Pfad zu entfernen, um den Dateinamen in var1 mit var2 vergleichen zu können.
var1Num=$&#123;#var1&#91;*&#93;&#125;

var2=&#40; `find $inputDir -name "*.$fileExt1" | sed "s/.$fileExt1//g;s/$inputDir//g"` &#41;
var2Num=$&#123;#var2&#91;*&#93;&#125;

# Zählvariablen deklarieren
var1Counter=0
var2Counter=0
copyCounter=0

# Sammeln der Dateiennamen, zu denen sowohl eine .tgz- als auch .md5-Datei vorhanden ist 
for &#40;&#40;var1Counter=0;$var1Counter<$var1Num;var1Counter++&#41;&#41;
do
  for &#40;&#40;var2Counter=0;$var2Counter<$var2Num;var2Counter++&#41;&#41;
  do
    var1=$&#123;var1&#91;var1Counter&#93;&#125;
    var2=$&#123;var2&#91;var2Counter&#93;&#125;
     if &#91; "$var1" = "$var2" &#93;
     then
       copyList&#91;copyCounter&#93;=$&#123;var1&#91;var1Counter&#93;&#125;
      &#40;&#40;copyCounter++&#41;&#41;
     fi
  done
done

let copyCounter=$copyCounter-1
for &#40;&#40;i=0;i<$copyCounter;i++&#41;&#41;
do
  echo copyList&#58; $&#123;copyList&#91;$i&#93;&#125;
  cp -p $&#123;copyList&#91;$i&#93;&#125;.$fileExt1 $inputDir $outputDir
  cp -p $&#123;copyList&#91;$i&#93;&#125;.$fileExt2 $inputDir $outputDir
done
So, nun wird einigen sicherlich schon ins Auge stoßen, dass ich an der Stelle
Code:
var1=&#40; `find $inputDir -name "*.$fileExt1" | sed "s/.$fileExt1//g;s/$inputDir//g"` &#41;
Probleme bekomme: man müsste innerhalb der Variable $inputDir bzw. Parameter $1 die Slashes maskieren.
Hier bin ich irgendwie in einer Sackgasse gelandet...

Wie könnte ich dies bewerkstelligen? Oder anders gefragt: gibt es noch eine besser/einfachere Möglichkeit den Dateinamenvergleich usw. zu bewerkstelligen?

Sry für den langen Text, aber ich wollte die Situation möglichst genau schildern ;)


Nach oben
   
 Betreff des Beitrags:
BeitragVerfasst: 25. Feb 2009 15:00 
Offline
Benutzeravatar

Registriert: 11. Feb 2006 19:10
Beiträge: 3569
Ich würde das viel einfacher machen:
Alle Dateien finden, auf die die Maske passt, in eine Schleife abkippen. Dort gucken, ob die Partnerdatei existiert. Wenn ja, beide Dateien kopieren.
Code:
#!/bin/bash 
 
inputDir=$1 
outputDir=$2 
fileExt1=$3 
fileExt2=$4

find $inputDir -name "*.$fileExt1" | while read thisFile
do
  otherFile=$&#40;dirname $thisFile&#41;/$&#40;basename $thisFile .$fileExt1&#41;.$fileExt2
  &#91; -f $otherFile &#93; && cp $thisFile $otherFile $outputDir
done
Janka

_________________
Ich vertonne Spam immer in /dev/dsp statt /dev/null.
Ich mag die Schreie.


Nach oben
   
 Betreff des Beitrags:
BeitragVerfasst: 26. Feb 2009 13:17 
Ohje, wenn ich mir diese paar Zeilen so anschaue wird mir klar, dass ich es nicht hätte umständlicher machen können.

Allerdings erschließt sich mir nicht so recht die Logik in der while-Schleife.

Nun ergibt sich auch noch die Frage:
Wie kann ich innerhalb der Dateisuche und des Kopiervorgangs (bzw. sollen die Dateien verschoben werden, nicht kopiert) Returncodes abfangen? Ich möchte folgende Returncodes nutzen:
0 -> es wurden Dateien verarbeitet
4 -> es lagen keine Dateien zuer Verarbeitung vor
8 -> Fehler: Schreibschutz auf Datei, die verschoben werden soll
12 -> Input oder Outputverzeichnis nicht gefunden, kein Speicherplatz im Outputdirectory

Bin irgendwie nicht in der Lage das in deine Schleife zu packen :/


Nach oben
   
 Betreff des Beitrags:
BeitragVerfasst: 26. Feb 2009 14:56 
Offline
Benutzeravatar

Registriert: 11. Feb 2006 19:10
Beiträge: 3569
Zitat:
Allerdings erschließt sich mir nicht so recht die Logik in der while-Schleife.
find ... gibt eine Liste aus Dateinamen aus, auf die das Muster "*.$fileExt1" passt. Diese Liste wird von der while-Schleife zeilenweise mittels "read" gelesen. Die gelesene Zeile landet in $thisFile (z.B "20090220_132010_blabla.md5"). Daraus konstruiert otherFile=... jeweils den Namen der Partnerdatei (hier: "20090220_132010_blabla.tgz")
Im nächsten Schritt wir geguckt, ob diese Partnerdatei existiert und eine normale Datei ist [ -f $otherFile ], wenn das der Fall ist (&&) werden beide kopiert (cp ...).
Zitat:
Wie kann ich innerhalb der Dateisuche und des Kopiervorgangs (bzw. sollen die Dateien verschoben werden, nicht kopiert) Returncodes abfangen? Ich möchte folgende Returncodes nutzen:
0 -> es wurden Dateien verarbeitet
4 -> es lagen keine Dateien zuer Verarbeitung vor
8 -> Fehler: Schreibschutz auf Datei, die verschoben werden soll
12 -> Input oder Outputverzeichnis nicht gefunden, kein Speicherplatz im Outputdirectory
Irgendein Grund, genau diese Zahlen für die Returncodes zu nehmen?

Fehlerbehandlung in der Shell ist immer etwas komplizierter, weil man ja fast alles mit externen Programm macht und es daher notwendig ist, alle möglichen Fehler dieser Programme zu verarbeiten, wenn man alles abfangen will. Umgekehrt musst du dich aber auch auf die Fehlerbilder beschränken, die du eindeutig ermitteln kannst.

Deine Fehler 8 und 12 kannst du ermitteln, indem du das Ergebnis von "cp" überwachst. Deinen Fehler 4 bekommst du raus, indem du in der Schleife irgendwo eine Variable setzt, und später außerhalb prüfst, ob diese gesetzt wurde.

Im übrigen kann man auch Dateien verschieben oder löschen, die schreibgeschützt sind. Verschieben oder Löschen erfordert nämlich nur das Recht, das Directory zu ändern in dem sich der jeweilige Datei*name* befindet.

Janka

_________________
Ich vertonne Spam immer in /dev/dsp statt /dev/null.
Ich mag die Schreie.


Nach oben
   
 Betreff des Beitrags:
BeitragVerfasst: 26. Feb 2009 15:46 
Noch einmal ein dickes danke an dich, auch für die ausführliche Erklärung des Codes!

Und ja, die Returncodes müssen so verwendet werden, da diese in einem späteren Schritt von anderen, bereits vorhandenen, Scripten abgefragt und verwendet werden.

Ich kam nun auf die glorreiche Idee in die Schleife einen Counter einzubauen, um auch die Anzahl der kopierten Dateien zu erfassen:
Code:
counter=0

# Dateien einlesen, vergleichen und kopieren
find $inputDir -name "*.$fileExt1" | while read thisFile
do
  otherFile=$&#40;dirname $thisFile&#41;/$&#40;basename $thisFile .$fileExt1&#41;.$fileExt2
  echo "DIRNAME&#58; $&#40;dirname $thisFile&#41;"
  echo "BASENAME&#58; $&#40;basename $tisFile .$fileExt1&#41;"
  echo "BASENAME&#58; $&#40;basename $tisFile .$fileExt1&#41;.$fileExt2"
  &#91; -f $otherFile &#93; && cp $thisFile $otherFile $outputDir
  &#40;&#40;counter++&#41;&#41;
  echo "INNERHALB SCHLEIFE&#58; $counter"
done

echo "AUSSERHALB SCHLEIFE&#58; $counter"
Problem:
echo "INNERHALB SCHLEIFE: $counter" zeigt mir immer korrekt die Anzahl der kopierten Dateien an, echo "AUSSERHALB SCHLEIFE: $counter" jedoch nicht. Die Variable $counter hat außerhalb der Schleife immer den Wert, den ich ihr ganz zu Beginn des Programms mit counter=0 zuweise... warum? :(


Nach oben
   
 Betreff des Beitrags:
BeitragVerfasst: 26. Feb 2009 23:30 
Offline
Benutzeravatar

Registriert: 11. Feb 2006 19:10
Beiträge: 3569
Zitat:
Problem:
echo "INNERHALB SCHLEIFE: $counter" zeigt mir immer korrekt die Anzahl der kopierten Dateien an, echo "AUSSERHALB SCHLEIFE: $counter" jedoch nicht.
Das ist logisch, denn für jede Pipeline " | while ..." muss eine zusätzliche Shell-Instanz gestartet werden. Der Code in der Schleife wird also in einem anderen Prozess ausgeführt als der außerhalb der Schleife. Um Daten zurück nach außerhalb zu geben, musst du daher eine Hilfsdatei benutzen, oder auf die Standardausgabe schreiben und diese außen wieder einlesen.
Code:
# Dateien einlesen, vergleichen und kopieren 
counter=$&#40;find $inputDir -name "*.$fileExt1" | while read thisFile 
do 
  otherFile=$&#40;dirname $thisFile&#41;/$&#40;basename $thisFile .$fileExt1&#41;.$fileExt2 
  echo >&2 "DIRNAME&#58; $&#40;dirname $thisFile&#41;" 
  echo >&2 "BASENAME&#58; $&#40;basename $tisFile .$fileExt1&#41;" 
  echo >&2 "BASENAME&#58; $&#40;basename $tisFile .$fileExt1&#41;.$fileExt2" 
  &#91; -f $otherFile &#93; && cp $thisFile $otherFile $outputDir 
  printf "x"
done | wc -c&#41; 

echo >&2 "AUSSERHALB SCHLEIFE&#58; $counter" 
>&2 gibt auf die Standardfehlerausgabe aus. Nützlich für Debugzwecke. printf hat gegenüber echo den Vorteil, dass man die Ausgabe besser formatieren kann. Unter anderem gibt es ohne Auftrag kein \n aus. "wc -c" zählt die Anzahl der Zeichen ("x"se), die in der Schleife ausgegeben wurden. Dies entspricht der Zahl der Schleifendurchläufe und somit der Dateien.

Shellprogrammierung ist halt oft mal etwas durch die Brust ins Auge...

Janka

_________________
Ich vertonne Spam immer in /dev/dsp statt /dev/null.
Ich mag die Schreie.


Nach oben
   
Beiträge der letzten Zeit anzeigen:  Sortiere nach  
Ein neues Thema erstellen  Auf das Thema antworten  [ 6 Beiträge ] 

Alle Zeiten sind UTC+01:00


Wer ist online?

Mitglieder in diesem Forum: 0 Mitglieder und 0 Gäste


Sie dürfen keine neuen Themen in diesem Forum erstellen.
Sie dürfen keine Antworten zu Themen in diesem Forum erstellen.
Sie dürfen Ihre Beiträge in diesem Forum nicht ändern.
Sie dürfen Ihre Beiträge in diesem Forum nicht löschen.
Sie dürfen keine Dateianhänge in diesem Forum erstellen.

Suche nach:
Gehe zu:  
cron
Powered by phpBB® Forum Software © phpBB Limited
Deutsche Übersetzung durch phpBB.de