Ich hab ein kleines Problem. Ich muss für GdI1 diese Aufgabe machen aber komm nicht wirklich weit.
Hier die Aufgabenstellung:
Schreiben Sie ein Shellskript convert.bash, das für ein beliebiges Verzeichnis alle dort enthaltenen Dateien mit einer
als Parameter übergebenen Endung (z.B. .doc) in das aktuelle Verzeichnis kopiert und die Endung austauscht gegen
eine als weiterer Parameter übergebenen Endung (z.B. .txt).
Alles was ich bis jetzt hinbekommen hab, war das eine bestimmte Datei zwar kopiert wurde und umbenannt aber nicht richtig umbenannt wurde.
hier das S*****
#!/bin/sh
for i in $1/*.txt
do cp "$i" *.TXT
done
für .txt und .TXT müssen Parameter eingesetzt werden
es sollte dann so geschrieben werden: ./convert.bash (verzeichnis) (dateiendung1) (dateiendung2)
Hilfe und erklärungen wie das gemacht wurde nehm ich gerne an
der Stern[*] wird immer durch eine Zeichenkette ersetzt, der übereinstimmt. *.txt liefert dir also korrekt einen String mit allen Datein mit dem Namen IRGENDWAS.txt und legt pro durchgang einen Dateinamen in $i ab. Jedoch wird der Inhalt von * nicht gespeichert (und selbst wenn, würde das ganze aus einem String aller Datein bestehen, die mit .txt enden und nicht nur der einen Datei von dem Durchgang), somit wird dann bei deinem Umbennenungsversuch bei *.TXT, nicht der Präfix von *.txt zurückgegeben, sondern ein String mit allen Datein, die IRGENDWAS.TXT heißen. Somit versuchst du so ca. soetwas: "cp DATEI.txt datei1.TXT datei2.TXT datei3.TXT dateiN.TXT . cp hat aber die Angewohnheit, bei mehr als 2 Parametern, alle Datein in das Verzeichnis (was im letzten Parameter angegeben ist) zu kopieren, was ja nicht dein Ziel ist .
Um den Suffix zu verändern, würde ich dir sed empfehlen, was auf jedem Unix dabei sein sollte. Dazu musst du nur die vorletzte Zeile anpassen.
hier die Lösung, wenn du zu "faul" bist selbst zu tüfteln...
Code:
#!/bin/sh
for i in $1/*.txt
do cp "$i" `echo "$i" | sed 's/\.txt$/.TXT/g'`
done
Diese nach links geneigten Anführungszeichen übergeben die Ausgabe (stdout) als Parameter. Also die Ausgabe die die Befehle innerhalb von `` liefern, werden an dieser Stelle als Parameter eingesetzt.
echo "$i" übergibt (dank Pipe ( | )) den Aktuellen Dateinamen an die Eingabe (stdin) von sed, dieser sucht und ersetzt (s) den regulärer Ausdruck (also .txt, jedoch muss es am Ende ($) stehen) durch die Zeichenfolge ".TXT".
Dadurch wird also an cp, als zweiten Parameter, der Inhalt von $i eingetragen, mit dem Unterschied, dass .txt durch .TXT ersetzt worden ist.
Wenn du jetzt noch " \.txt$ " durch " '$var1' " und " .TXT " durch " '$var2' " ersetzt, bist du so gut wie fertig
Also die übergebenen Paramter liest du ganz einfach mit $1 $2 $3 aus. Aber das hast du ja sicher auch schon bemerkt, sonst hättest du ja nicht in der for schleife $1 geschrieben
Das skript sieht bei mir letztendlich so aus:
Code:
1: #!/bin/sh
2: for i in $1/*.$2
3: do cp $i ${i%$2}$3
4: done
Erklärung zu Zeile 3: mit dem Statement {i%$2} wird dem interpreter quasi nur gesagt das er aus der Zeichenkette $i von rechts nach links das erste aufkommen der zeichenkette $2 löschen soll. Durch die $3 dahinter soll er dann die andere Dateiendung dranhängen. Der Punkt ist ja noch vorhanden, da man ja bei der Parameterübergabe, laut deinem Beispiel, nur die Endung ohne Punkt übergibt.
Viele Grüße
Josum
EDIT: Oh, da war wohl einer schneller... nichts für ungut
Die Lösung von josum wird aber nur von der bash und der csh unterstützt (nur wichtig, wenn es quasi überall lauffähig sein soll) aber sonst ist es halt übersichtlicher als sed.
Eine weiterer Ansatz wäre die Verwendung von "basename". Damit kann man auch einen Suffix entfernen, aber leider auch immer den Pfad davor (dafür gibt es dann aber dirname; beides gehört zu posix und sollte daher auch bei jeder Linux Distribution dabei sein).
Aber wie heißt es so schön ... Viele Wege führen nach Rom ...
Ich hab beide Sachen ausprobiert.
Bei der von Josum hat er die Datei kopiert und auch die Dateiendung verändert wie gewollt, aber leider alles im ausgewählten Ordner.
Was mir auch aufgefallen ist,dass nur eine Datei verändert wird. Es müssen aber alle Datein mit der gleichen Endung verändert werden
Nachdem ich das in vi eingetippt hab,hab ich anschließend chmod u+x gemacht
dann ./convert.bash(so heißt die datei) Dokumente(das beliebige Verzeichnis) txt doc
er hat halt die Datei nicht in ./ gelegt sondern in Dokumente
Bei der Lösung von slahn hab ich wie erklärt die Sachen ausgetauscht,
#!/bin/sh
for i in $1/*.txt
do cp "$i" `echo "$i" | sed 's/\$var1/$var2/g'`
done
aber dann kommt immer
mint@mint ~ $ ./test.bash Dokumente txt zip
cp: `Dokumente/Test.txt' and `Dokumente/Test.txt' are the same file
cp: target `test.txt' is not a directory
Hoffe ihr könnt mir da weiterhelfen, also das erste ist gut es fehlt nur noch das er es in den aktuellen Ordner kopiert/verändert
Du hast bei meinem Code die single quotes vergessen. Damit sed mit Umgebungsvariablen arbeiten kann, muss man die single quotes schließen, da ja sed sonst $var1 bekommt und nicht den Inhalt. Zudem war $var1 nur ein Beispiel ...
Aber hier die komplette Lösung, die auch in der sh laufen sollte (getestet mit der dash):
Code:
#!/bin/sh
for source_file in $1/*.$2
do
cp $source_file "`basename $source_file ".$2"`.$3"
done
exit 0
Parameter 1 ($1) muss den Pfad enthalten; Parameter 2 ($2) den gesuchten Suffix (ohne Punkt); Parameter 3 ($3) den neuen Suffix (ohne Punkt);;
Alle die Dateien werden in das aktuelle Verzeichnis kopiert.
[Hab mich jetzt für basename entschieden, da du es ja eh ins aktuelle Verzeichnis kopieren willst und man mit sed noch selbst das Verzeichnis entfernen müsste (sed ist zwar sehr flexibel und kann mit Texten so gut wie alles machen, aber wenn es schon eine fertige Lösung gibt, muss man ja das Rad nicht neu erfinden ...)]
Super, hab es grade getestet. Es funktioniert alles. Danke euch beiden für die schnelle Hilfe und auch die Erklärungen dafür.
Das hat mir sehr geholfen.