wildcards unter HP-UX

N

Nergal

Grünschnabel
Hallo,
zum Problem:

Ich arbeite unter HP-UX und habe eine ganze Reihe von Postscript Grafiken, welche ich in eps Dateien mit Vorschau konvertieren moechte. Bei einzelnen Dateien ist das ganze mittels des Befehls pstoepsi kein Problem.

Verwende ich jedoch Platzhalter um den gesamten Ordner zu konvertieren, dann streikt die shell :

Code:
pstoepsi *.ps *.epsi

Daher die Frage:
Gibt es eine unkomplizierte Moeglichkeit um diese Aufgabe zu bewaeltigen? Natuerlich koennte ich ein Shell Skript schreiben, allerdings geht es mir vor allem darum zu verstehen, wie ich unter HP-UX vernuenftig mit Wildcards arbeiten kann.

Ich bin fuer jeden Vorschlag dankbar.
 
Ich fuerchte nein, pstoepsi kann halt nicht mit mehreren Inputfiles umgehen ...
ich wuerde das an der Kommandline so machen:

for i in `ls -1 *.ps`
do
ps2epsi ${i}
done

sers,
allesmueller
 
Wie schon von allesmueller angedeutet, ist dies sicher kein Problem von HP-UX, sondern am Argument-Parsing von pstoepsi.

Falls Du die Endung gerne auf epsi setzen moechtest, geht uebrigens auch folgende Loesung (unter bash):
Code:
for i in *.ps; do pstoepsi $i ${i%ps}epsi ; done
 
rikola,
yepp gute Idee - ich verwend kaum bash syntax,
ich kack dann immer mit "basename" herum :)

in diesem Fall aber nicht notwendig, da das Programm das selbst macht.

sers,
allesmueller
 
Danke fuer die schnellen Antworten!

Der Einzeiler von rikola hat gluecklicherweise auch mit der korn shell funktioniert, so dass alle Dateien erfolgreich konvertiert werden konnten. Danke :)

Trotzdem wuerde es mich sehr interessieren, warum der Shell Interpreter diese Funktionaliaet nicht selbstaendig uebernimmt? Meines Erachtens waere es sehr intuitiv erst die wildcards auszuwerten und somit vorab eine Dateiliste(tabelle) zu erstellen. Im zweiten Schritt wuerde dann die Anwendung des Kommandos (in diesem Fall pstoepsi) auf jeden Listeneintrag erfolgen.

Kennt jemand die Hintergruende fuer diese Auslegung des Interpreters?
 
Woher soll die Shell wissen, welcherart Parameter einzelne Programme verlangen? Es gibt Programme/Befehle, die mit multiblen Parametern arbeiten können oder sie auch brauchen. Als Beispiel, wie nach Deiner Vorstellung "ls -l -a dirname" abgearbeitet wird: "ls -l", anschliessend "ls -a" sowie dann "ls dirname". Ist wohl nicht der Sinn der Sache, oder? ;)
 
Keine Angst, das waere wirklich nicht Sinn der Sache ;).
Ich meine das ganze rein im Bezug auf die Wildcards in Eigennamen (z.B. von Dateinamen, Verzeichnisnamen, oder Textstrings in Suchabfragen). Die Abarbeitung von Parametern sollte dabei nach wie vor komplett geschehen. Das heisst beim Abarbeiten von von "ls -l -a dirname" wird genau einmal das Kommando "ls" angewendet, und zwar auf den Ordner "dirname" und mit den Parametern "-l -a".

Bei einer Eingabe von z.B. "ls -l -a dirname*" wuerde dann zuerst vom Interpreter festgestellt werden, wieviele Verzeichnisse in die Abfrage fallen. Gibt es also die Verzeichnisse "dirname1", "dirname2" und "dirname3", dann werden die drei Strings in eine Liste geschrieben. Danach wird das Kommando "ls -l -a" auf jedes Element der Liste einmal angewendet, so dass der Inhalt aller drei Verzeichnisse ausgegeben wird.

Ich hoffe ich konnte die Idee etwas verstaendlicher machen.
 
Du willst also eine intelligente Shell, die die Optionen eines Befehls/Programms erkennt?

Ich nenn mal noch ein paar Beispiele, bei denen diese intelligente Shell Probleme hätte:

Code:
diff file1 file2
cat file1 file2 > file
find . -name "muster*"

Am find-Befehl sieht man, dass Optionen mannigfaltig aussehen können. Woher weiss die Shell, dass "muster*" zur Option gehört und nicht von der Shell ausgewertet werden soll. Und jeder, der schonmal ein Programm/Skript mit Parametern geschrieben hat, würde mit dieser intelligenten Shell seine Probleme haben.

Sehe es mal so, auf der einen Seite bist Du genötigt, einen for-Einzeiler zu schreiben, auf der anderen Seite verliert die Shell viel von ihrer Flexibilität.

Gruss, Phorus
 
Die Interpretation von wildcards etc. wird in der bash-documentation sehr ausfuehrlich erklaert ('info bash'). Die Argumente werden von der bash nich "abgearbeitet", sondern expandiert. Es liegt also kein dynamischer Prozess vor, der Befehl bekommt einen String zugewiesen, _nachdem_ bash ihn interpretiert hat.
 
@rikola
Ich verwende ksh, aber prinzipiell ist es da nich anders als bei bash. Im Grunde genommen ist mein Problem durch deinen Tip ja auch schon mittels einer sehr einfach Variante geloest.

Alles weitere ist rein hypothetischer Natur, da ich weder bash noch die ksh aendern wollen wuerde, geschweige denn so einfach koennte.

Wie gesagt, fuer mich waere es intuitiver den Interpreter anders aufzubauen. Da sich die Entwickler jedoch sehr wahrscheinlich um einiges mehr an Gedanken gemacht haben, als ich in meiner Fruehstueckspause ;) , geht es mir vor allem darum zu verstehen, welche Probleme eine Auslegung nach meinem Vorschlag mit sich bringen wuerde. Wie gesagt, rein hypothetisch.

@Phorus
Bei dem diff Beispiel wuerde ich keine Probleme sehen, bei cat eventuell, aber bei find hast du in der Form sicherlich recht. Probleme wuerde es in jedem Fall geben, wenn wildcards in den Kommandooptionen auftauchen. In diesem Fall haette der Interpreter keine Moeglichkeit zu Unterscheiden, welche Wildcards er selbst auswerten soll und welche lediglich an das Kommando uebergeben werden sollen. Das wuerde auf jeden Fall die meisten Programme/Skripte durcheinanderwirbeln.
Eventuell koennte man jedoch die volle Flexibilitaet der Shell beibehalten, wenn man ein spezielles Tag benutzt, um Wildcards fuer die Shell von denen fuer das Kommando unterscheiden zu koennen. Sprich "muster*" wird als reiner Optionsparameter uebergeben und das * wird vom Interpreter nicht ausgewertet. Der Befehl wird somit korrekt ausgefuehrt. Bei einer Eingabe von "muster^*" z.B., wobei ^ natuerlich ein exklusives Symbol sein muesste, wuerde dann _keine_ Wildcard an den Kommandonamen uebergeben. Stattdessen wuerde bei z.B. 10 Treffern zehnmal der find Befehl mit den angegebenen Paramentern, aber je fuer ein anderes Verzeichnis augefuehrt werden. Das Ergebnis muesste dabei qualitativ dem von "muster*" sein.

Ich hoffe ich habe mich nicht zu kompliziert ausgedrueckt.

Ich freue mich weiterhin ueber jede Antwort!
 
Zuletzt bearbeitet:
Nergal schrieb:
@Phorus
Bei dem diff Beispiel wuerde ich keine Probleme sehen, bei cat eventuell, aber bei find hast du in der Form sicherlich recht. Probleme wuerde es in jedem Fall geben, wenn wildcards in den Kommandooptionen auftauchen. In diesem Fall haette der Interpreter keine Moeglichkeit zu Unterscheiden, welche Wildcards er selbst auswerten soll und welche lediglich an das Kommando uebergeben werden sollen. Das wuerde auf jeden Fall die meisten Programme/Skripte durcheinanderwirbeln.
Eventuell koennte man jedoch die volle Flexibilitaet der Shell beibehalten, wenn man ein spezielles Tag benutzt, um Wildcards fuer die Shell von denen fuer das Kommando unterscheiden zu koennen. Sprich "muster*" wird als reiner Optionsparameter uebergeben und das * wird vom Interpreter nicht ausgewertet. Der Befehl wird somit korrekt ausgefuehrt. Bei einer Eingabe von "muster^*" z.B., wobei ^ natuerlich ein exklusives Symbol sein muesste, wuerde dann _keine_ Wildcard an den Kommandonamen uebergeben. Stattdessen wuerde bei z.B. 10 Treffern zehnmal der find Befehl mit den angegebenen Paramentern, aber je fuer ein anderes Verzeichnis augefuehrt werden. Das Ergebnis muesste dabei qualitativ dem von "muster*" sein.

Ich hoffe ich habe mich nicht zu kompliziert ausgedrueckt.

Ich freue mich weiterhin ueber jede Antwort!

Du kannst doch die Wildcards mit einem \ versehen, dann werden sie nicht interpretiert. Oder Du bettest sie in Einzelhochkammata, dann werden sie ebenfalls nicht interpretiert ( ls '*' ). Ich kenne kein Programm ausser den Shells, dass wildcards interpretiert. Wenn Du etwas 10x separat ausfuehren moechtest, benutzt Du einfach eine for- oder while-Schleife. Vielleicht kann die sh schon alles, was Du suchst, und Du musst Dich nur noch ein bisschen mit ihr vertraut machen.
 
Hmm der find-Befehl war nicht so clever gewählt, da durch die "" um muster* verhindert wird, dass die Shell diese Wildcard auswertet. Das Beispiel "diff file1 file2" zeigt besser, dass mehrere File/Dir-Namen als Parameter manchmal vonnöten sind, weil "diff file1 file2" nunmal nicht gleich "diff file1" und "diff file2" ist.

Gruss, Phorus

edit:

rikola schrieb:
...
Ich kenne kein Programm ausser den Shells, dass wildcards interpretiert.
...

find, perl... ;)
 
Zuletzt bearbeitet:
Phorus schrieb:
...Das Beispiel "diff file1 file2" zeigt besser, dass mehrere File/Dir-Namen als Parameter manchmal vonnöten sind, weil "diff file1 file2" nunmal nicht gleich "diff file1" und "diff file2" ist...

Hmm, ich fuerchte wir reden immer noch etwas aneinander vorbei. Mir ging es nie darum, dass jeweils nur ein Parameter ausgewertet wird. Da das Beispiel "diff file1 file2" keine Wildcards enthaelt wuerde es natuerlich so wie immer ausgewertet werden. Und auch mit Wildcards wuerde diff immer mit zwei File/Dir-Namen aufgerufen werden. Nur eben quasi als Batch mehrmals hintereinander mit wechselnden File/Dir-Namen.
 
Du möchtest also, dass die Shell den Parameter-Syntax jedes Befehls/Programmes kennt? ;)
 
Nein. Die Shell ist schon darauf angewiesen, dass der Benutzer den richtigen Syntax verwendet.
Das ganze setzt vorraus, dass die Shell Wildcards mit Datei-/Verzeichnisnamen verknuepft. Also wenn in einem String ein Wildcard auftaucht, dann interpretiert die Shell den String als Verzeichnis oder Dateinamen. Dafuer ist es fuer die Shell erstmal uninteressant, welchen Syntax das letztendliche Kommando erwartet.
 
Nichts anderes macht die Shell. Irgendwie reden wir aneinander vorbei. Nochmal von vorne:

- Du willst, dass die Shell Wildcards auswertet und in File/Dir-Namen expandiert: Kein Problem: das machen Shells.

- Wenn die Shell mehrere File/Dir-Namen expandiert, soll die Shell diese in einem Array speichern und das Programm jeweils mit jedem File/Dir-Namen einzeln aufrufen: das ist zu restriktiv, da diverse Befehle/Programme mit mehreren File/Dir-Namen umgehen können/müssen (Bsp: diff, cat), und deswegen machen Shells sowas nicht :)

edit: Tippfehler
 
Zuletzt bearbeitet:
Phorus schrieb:
Irgendwie reden wir aneinander vorbei.
Meine Rede ;)

Phorus schrieb:
- Du willst, dass die Shell Wildcards auswertet und in File/Dir-Namen expandiert

Exakt!

Phorus schrieb:
- Wenn die Shell mehrere File/Dir-Namen expandiert, soll die Shell diese in einem Array speichern...

Immer noch korrekt...

Phorus schrieb:
...und das Programm jeweils mit jedem File/Dir-Namen einzeln aufruft

Ab hier reden wir aneinander vorbei. Ich meine naemlich:

...und das Programm jeweils mit jeder gueltigen File/Dir-Namen Kombination aufruft

Ahnst du was ich meine? :) Ansonsten kann ich auch mal ein Beispiel in Pseudo Code angeben.
 
Nergal schrieb:
...
...und das Programm jeweils mit jeder gueltigen File/Dir-Namen Kombination aufruft

Ahnst du was ich meine? :) Ansonsten kann ich auch mal ein Beispiel in Pseudo Code angeben.

Arg...woher soll denn die Shell wissen, was gültig ist? Try and Error? Auf den Pseudo Code bin ich gespannt, wenn er hilft, hier Klarheit reinzubringen ;)
 
Nergal schrieb:
...und das Programm jeweils mit jeder gueltigen File/Dir-Namen Kombination aufruft
Ja aber genau dort liegt doch schon das Problem, wie Wolfgang bereits meinte: Die Gueltigkeit ist programmabhaengig, also muesste die Shell doch das Programm kennen, an das es die Parameter weiterleitet, und das kann sie nicht, allein schon deshalb, weil sich jeder seine eigenen Programme schreiben kann. Aber das hast Du ja auch schon akzeptiert.

Stattdessen stellt die Shell dem Benutzer die Moeglichkeiten zur Verfuegung, dies gueltigen Kombinationen recht einfach zu generieren, angepasst auf das aufzurufende Programm. Das ist doch viel mehr, als das was Du haben moechtest, oder nicht? Wenn nicht, tipp doch mal zwei unterschiedliche Beispiele ein, die die Shell bewerkstelligen sollte.
 
Ok, sich sehe schon, wir drehen uns irgendwie im Kreis :)

Also doch der Pseudocode. Als Beispiel nehme ich mal das allseits liebgewonnene "diff file1 file2"

Annahme:
Im Verzeichnis befinden sich die folgenden drei Dateien:

file1.txt
file2.txt
file3.txt


Ziel:
Ich moechte die Dateien miteinander vergleichen und die Unterschiede auf den Bildschirm sehen.

Aufruf in der Kommandozeile:"
Code:
diff file*.txt file*.txt
Parsing der Eingabe (vom Interpreter/Shell)
1. Lese String #1 (in diesem Fall diff) und schreibe den Inhalt auf den Kommando Stack. Am Anfang steht immer der auszufuehrende Befehl

2. Lese den Rest der Eingabe und schreibe den Inhalt auf den Stack Temp1. Nach dem Kommando kommen weitere Optionen/Parameter/Dateinamen/Verzeichnisnamen etc.

3. Filtere den Inhalt von Temp1. Die Divider zwischen den einzelnen Elementen sind die Leerzeichen. Es werden also zwei Elemente erkannte, naemlich
Code:
 e[0] = "file*.txt"
und
Code:
e[1] = "file*.txt"

4.
Code:
<HasWildcard>
for i=0;i<length(e[]);++i do:
    {
       Enthaelt i ein *? (Ja/Nein)
       {
          Wenn ja:
             Goto <MakeArray>
          Wenn nein:
             passiert nix
        }
     }
Enthaelt das Element ein Wildcard, dann wird die Prozedur <MakeArray> ausgefuehrt.

5. <MakeArray>
Die Prozedur <MakeArray> sucht nach Dateien, welche mit "file" beginnen und die Endung "txt" haben. Also quasi identisch mit dem herkoemmlichen Befehl "l file*.txt". Alle Treffer werden in das Array "HitTable_i[]" geschrieben. (Ueber dynamische Variablennamenerzeugung machen wir uns jetzt mal keine Gedanken ;) )

Die Prozedur <HasWildcard> laueft also zweimal durch und ruft jeweils die Prozedur <MakeArray> auf. Dabei werden die beiden Arrays "HitTable_0" und "HitTable_1" geschrieben. Der Inhalt der Arrays lautet wie folgt:
Code:
HitTable_0 = {file1.txt, file2.txt, file3.txt};
HitTable_1 = {file1.txt, file2.txt, file3.txt};

6. Stapelverarbeitung
Zu guter Letzt wird nun das Kommando diff ausgefuehrt:
Code:
<BatchExecute>
for i=0;i<length(HitTable_0[]);++i do:
{
    for j=0;j<length(HitTable_0[]);++j do:
    {
         diff HitTable_[i] HitTable_[j];
     }
}


Das Ergebnis davon waere equivalent zu einem neunmaligen aufrufen von "diff", genaugenommen:
Code:
diff file1.txt file1.txt
diff file1.txt file2.txt
diff file1.txt file3.txt
diff file2.txt file1.txt
diff file2.txt file2.txt
diff file2.txt file3.txt
diff file3.txt file1.txt
diff file3.txt file2.txt
diff file3.txt file3.txt

Ist die Idee jetzt verstaendlicher? Ansonsten gehen mir langsam die Optionen aus...

Ja aber genau dort liegt doch schon das Problem, wie Wolfgang bereits meinte: Die Gueltigkeit ist programmabhaengig

Kleines Missverstaendnis. Mit Gueltigkeit meine ich nicht die Gueltigkeit des Syntax, sondern lediglich die existierenden Datei-/Verzeichnisnamen, welche man mit dem Wildcard finden kann.

Stattdessen stellt die Shell dem Benutzer die Moeglichkeiten zur Verfuegung, dies gueltigen Kombinationen recht einfach zu generieren, angepasst auf das aufzurufende Programm. Das ist doch viel mehr, als das was Du haben moechtest, oder nicht?
Keine Frage, ich bin genauso froh wie du, dass es die Shell gibt, ehrlich. Und das ich damit so gut wie alles machen kann steht hier auch nicht zur Diskussion.

Mein Anliegen resultiert daraus, das nahezu alle Shellkommandos Operationen auf Dateien und Verzeichnisse bewerkstelligen. Von daher finde ich es gar nicht so abwegig eine moeglichst kompakte Moeglichkeit zu haben, um kommandos (welcher Art auch immer) auch auf verschiedene Dateien anwenden zu koennen. Und kompakter als Wildcards geht es nimmer ;).

Wuerde ein Shell Interpreter sich um diese Funktionalitaet bereits kuemmern, dann muesste sich der Ersteller eines Programms ueberhaupt keine Gedanken mehr darueber machen. Ein Kommando wie z.B. das anfaengliche pstoepsi wuerde dann Problemlos auf multiple Dateien funktionieren, genauso wie eine Vielzahl anderer Kommandos. Ohne diese Funktionalitaet muss man entwerder hoffen, dass der Programmierer einen Parameter dafuer eingebaut hat, oder man schreibt sich halt ein Shell Skript (Was wie gesagt auch nicht zu beanstanden ist).
 
Zuletzt bearbeitet:
Zurück
Oben