Moin, Frage zur Shell: nehmen wir an, ich habe sowas: datei="egal.tmp" mv $datei wichtig.tmp Wie kann ich sicherstellen, daß das immer funktioniert, auch wenn $datei völlig kranke Dateinamen enthält? Also beispielsweise sowas wie: 5 1/2"-Diskette.jpeg Bei dem Projekt, an dem ich gerade schraube, ist _alles_ möglich, daher reicht es mir nicht, zu schreiben mv "$datei" "wichtig.tmp" Gibt es eine Möglichkeit, das zu quoten/escapen/whatever? Wohlmöglich etwas, das in allen gängigen Shells funktioniert und nicht nur in der Bash? Ich bräuchte doch wohl als das Resultat: 5\ 1\/2\"-Diskette.jpeg Oder? Sehr gern auch für perl, da kommen die Daten ohnehin her. Gruß und Danke, Ratti -- http://www.gesindel.de | Fontlinge | Die Schriftenverwaltung für Windows
Hallo Ratti, * ratti schrieb am 12.Jun.2002:
nehmen wir an, ich habe sowas:
datei="egal.tmp" mv $datei wichtig.tmp
Wie kann ich sicherstellen, daß das immer funktioniert, auch wenn $datei
mv "$datei" wichtig.tmp
völlig kranke Dateinamen enthält? Also beispielsweise sowas wie:
5 1/2"-Diskette.jpeg
Das geht allerdings grundsätzlich nicht. Keine Datei kann ein / in ihrem Namen enthalten, da der / (slash) der Trenner der Pfadbestandteile ist. / und das ASCII-Zeichen NUL gehen nicht, sonst alles.
Bei dem Projekt, an dem ich gerade schraube, ist _alles_ möglich, daher reicht es mir nicht, zu schreiben
mv "$datei" "wichtig.tmp"
Genauso, wobei im zweiten Teil die " überflüssig sind.
Gibt es eine Möglichkeit, das zu quoten/escapen/whatever? Wohlmöglich etwas, das in allen gängigen Shells funktioniert und nicht nur in der Bash?
Keine Ahnung, wie es in der csh und tcsh aussieht, aber ansonsten ist es überall so richtig, wie Du es oben geschrieben hast.
Ich bräuchte doch wohl als das Resultat: 5\ 1\/2\"-Diskette.jpeg
Oder?
Sehr gern auch für perl, da kommen die Daten ohnehin her.
Geht leider nicht. Hat nichts mit der shell zu tun. Würde auch nicht funktionieren, wenn Du es mit C machst, da macht der Kernel nicht mit. Bernd
Hallo_{Bernd,Ratti,*}, * Am 13.06.2002 um 00:39 Uhr schrieb Bernd Brodesser:
* ratti schrieb am 12.Jun.2002:
nehmen wir an, ich habe sowas:
datei="egal.tmp" mv $datei wichtig.tmp
Wie kann ich sicherstellen, daß das immer funktioniert, auch wenn $datei
mv "$datei" wichtig.tmp
völlig kranke Dateinamen enthält? Also beispielsweise sowas wie:
5 1/2"-Diskette.jpeg
Das geht allerdings grundsätzlich nicht. Keine Datei kann ein / in ihrem Namen enthalten, da der / (slash) der Trenner der Pfadbestandteile ist. / und das ASCII-Zeichen NUL gehen nicht, sonst alles.
da man davon ausgehen kann das die Datei bereits existiert, muß der Name gültig (wenn auch ungewöhnlich) sein. Probleme bereiten hier natürlich alle Zeichen die in der Shell eine besondere Bedeutung besitzen. Ein möglicher Lösungsansatz, der allerdings nur flüchtig von mir getestet wurde könnte so aussehen: Quote=$( echo "$datei" | sed -e 's/\"/\\\"/g' \ -e 's/\*/\\\*/g' \ -e 's/\?/\\\?/g' ) eval mv \""$Quote"\" wichtig.tmp -Jürgen -- Jede Aufgabe benötigt doppelt so viel Zeit wie Sie ansetzen. Verdoppeln Sie die Zeit, dauert die Aufgabe viermal so lang. / Registered Linux-User #130804 http://counter.li.org \ \ Linux Stammtisch Bremerhaven http://linux.hs-bremerhaven.de /
* Juergen Schwarting schrieb am 13.Jun.2002:
da man davon ausgehen kann das die Datei bereits existiert, muß der Name gültig (wenn auch ungewöhnlich) sein. Probleme bereiten hier natürlich alle Zeichen die in der Shell eine besondere Bedeutung besitzen. Ein möglicher Lösungsansatz, der allerdings nur flüchtig von mir getestet wurde könnte so aussehen:
Quote=$( echo "$datei" | sed -e 's/\"/\\\"/g' \ -e 's/\*/\\\*/g' \ -e 's/\?/\\\?/g' ) eval mv \""$Quote"\" wichtig.tmp
Nö, das ist nicht nötig. $ mkdir test $ cd test $ > datei\"\*\?\" \'name\' $ ls datei"*?" 'name' $ datei=datei\"\*\?\"\ \'name\' $ mv "$datei" test $ ls test Es reicht somit die Variable in "..." zu setzten. Egal was da drin steht. Nur ist grundsätzlich kein / in einem Dateiname möglich. Bernd -- Was ist quoten? Quoten ist das Zitieren aus einer mail, der man antwortet. Und wie macht man es richtig? Zitate werden mit "> " gekennzeichnet. Nicht mehr als nötig zitieren. Vor den Abschnitten das Zitat, auf das man sich bezieht, mit einer Zeile Abstand oben und unten. |Zufallssignatur 12
Hallo, Peter Wiersig:
Du nimmst perl um die Dateiliste herzustellen... kannst du nicht einfach perls rename function benutzen, um den Dateinamen zu veraendern?
Oder willst du ein Shell-Skript erzeugen?
ls -Q faellt mir noch ein.
Ich erkläre am Besten mal, was ich möchte. Ich setze gerade meine Fontverwaltung von Windows auf Linux um (www.gesindel.de). Verwendet wird perl und MySQL. Eine Fähigkeit des Programms besteht darin, aus einem TrueType-Font seinen Namen auszulesen und die Datei entsprechend umzubenennen. Streng nach Norm unterliegen die Dateinamen von TrueType-Fonts unter Windows immer noch der DOS(!)-Dateinamenkonvention. Daher heissen die meisten Schriften zum Beispiel "GARABI.TTF" statt "Garamond Bold Italic.ttf" Da die meisten Fonts "für Windows" gebastelt werden, betrifft das auch die Linuxer. Die Funktionen meines Programms möchte ich als include-Dateien veröffentlichen, damit sich auch andere bedienen können. So, nun gibt es aber Schriften, die heissen, warum auch immer, z.B. "Sabon*Bold". Mit Sternchen drin. Ich selbst werde in meinem Code filtern und den Font "Sabon_Bold.ttf" nennen. Ich möchte aber, das meine Subroutinen generell dazu in der Lage sind, auch mit Namen mit * ? | umzugehen. Ich hatte gehofft, es gäbe sowas wie "quotemeta()" in PHP. Man kann beliebige Strings damit behandeln und es kommt was "sicheres" dabei raus. Es sieht aus, als müsse ich mir da eine RE selber basteln. 8:-( Eigentlich fühle ich mich dafür gar nicht sicher genug. Gibt es irgendwo eine Liste aller "relevanten" Zeichen, die in sowas wie `mv $a $b` nicht vorkommen dürfen? Mir fällt dazu jetzt ein: * ? [ ] { } > < | " ` ' ' ~ ...ohje, das ist ja fast alles zwischen ASCII 33 und 64. Was mich wundert: Ich hatte eigentlich eine Fehlermeldung erwartet, wenn ich das hier machen: touch a\"b # Datei erzeugen die heisst a"b ...und dann ein Script starte, das so aussieht: a=`find ./ -name "a*"` echo $a mv "$a" "safename" Ich hatte erwartet, mv "$a" "safename" würde expandiert zu mv "a"b" "safename" und somit eine Fehlermeldung verursachen... Verdammt! Immer wenn man denkt, man hätte es kapiert! =%-) Gruß, Ratti -- http://www.gesindel.de | Fontlinge | Die Schriftenverwaltung für Windows
ratti wrote:
Ich erkläre am Besten mal, was ich möchte.
Ich setze gerade meine Fontverwaltung von Windows auf Linux um (www.gesindel.de). Verwendet wird perl und MySQL.
Eine Fähigkeit des Programms besteht darin, aus einem TrueType-Font seinen Namen auszulesen und die Datei entsprechend umzubenennen.
Die Frage ist, warum du dazu mv benutzen willst? Ein rename() in perl wird sicher nicht anfangen zu "glob"ben. Ich behaupte mal das perl die Anweisung rename("GARABI.TTF", "Garamond* Bold Italic.ttf") locker ausfuehren wird. (Klappt, sogar inklusive dem Zeilenumbruch :) Das solche Dateinamen auf der Shell kein Spass machen und gequotet werden muessen ist klar, aber doch nicht innerhalb von perl, oder? Peter
Hallo, Peter Wiersig:
Die Frage ist, warum du dazu mv benutzen willst? Ein rename() in perl wird sicher nicht anfangen zu "glob"ben. Ich behaupte mal das perl die Anweisung rename("GARABI.TTF", "Garamond* Bold Italic.ttf") locker ausfuehren wird. (Klappt, sogar inklusive dem Zeilenumbruch :)
Ich will nicht mv'en sondern cp'en :-) Meines Wissens gibt es in perl zwar "rename" als Äquivalent zu "mv", aber nix für "cp". Ich habe "File::Copy" angeguckt. Läuft bei mir nicht, was aber egal ist: Es kann ohnehin nicht kopieren unter Beibehaltung des original-Zeitstempels. Da ich nix schlaueres gefunden habe, verwende ich also derzeit in perl: `cp "$alter_name" "$neuer_name" -a`; Also Übergabe eines Befehls an die Shell. "-a" belässt den Zeitstempel. Wobei der Zielname mit s/\W/_/g behandelt wurde. Damit bin ich auf der sicheren Seite. Für mein Programm langt das, aber die Subroutinen hätte ich eigentlich gerne sicherer, da ich sie publizieren werde. Und derzeit werden ungefährliche Zeichen wie ! und + dadurch auch gekillt. Alternativen gerne gehört. Irgendwas in der Art von "Kopiere::Gnadenlos" :-) Gruß, Ratti -- http://www.gesindel.de | Fontlinge | Die Schriftenverwaltung für Windows
Hallo, On Thu, 13 Jun 2002, ratti wrote:
Ich will nicht mv'en sondern cp'en :-)
Meines Wissens gibt es in perl zwar "rename" als Äquivalent zu "mv", aber nix für "cp". Ich habe "File::Copy" angeguckt. Läuft bei mir nicht, was aber egal ist: Es kann ohnehin nicht kopieren unter Beibehaltung des original-Zeitstempels.
Schalt ein 'touch -a -r ORIGINAL KOPIE' dahinter...
Da ich nix schlaueres gefunden habe, verwende ich also derzeit in perl:
`cp "$alter_name" "$neuer_name" -a`;
Also Übergabe eines Befehls an die Shell. "-a" belässt den Zeitstempel. Wobei der Zielname mit s/\W/_/g behandelt wurde. Damit bin ich auf der sicheren Seite. Für mein Programm langt das, aber die Subroutinen hätte ich eigentlich gerne sicherer, da ich sie publizieren werde. Und derzeit werden ungefährliche Zeichen wie ! und + dadurch auch gekillt.
Alternativen gerne gehört. Irgendwas in der Art von "Kopiere::Gnadenlos" :-)
Teste mal mit folgendem: ==== #!/usr/local/bin/perl -w use strict; my ($safe, $tmp); [..] foreach(@ARGV) { $safe = $_; $safe =~ s/[^[:alnum:]]/_/g; $tmp = $safe . ".tmp"; rename($_, $safe); `cp $safe $tmp`; rename($tmp, $_); } ==== Ja, ich weiss, dass ist KRANK! Aber so bekommt das 'cp' nur sichere Dateinamen zu sehen ;) Experimentiere aber evtl. auch mit 'quotemeta'... Und mit stat vorher und `touch` hinterher muesste sich ggfs. die atime (usw.) wieder korrigieren lassen ;) Die Ersetzung aller ^[:alnum] kannst du natuerlich noch beliebig verfeinern ;) Achso: Woher kommen nochmal die kranken Dateinamen? Sind das schon vorhandene (und wenn ja, auf welchem FS?) oder liest du die erst aus den Dateien aus? Und noch ne Idee: experimentiere evtl. mal mit find ... -print0 | perl -e '... split("\0", ...); ...' So auf die schnelle hab ich aber nix hinbekommen ;) Ein ' | xargs -0' hilft in diesem Fall wohl auch nicht weiter... -dnh PS: Wer kranke Dateinamen verwendet, erlaubt oder in Umlauf bringt... -- hier ist es ja wie im Urlaub! Nix mehr zu tun. Kein Dau zu beerdigen. Kein Elch zu verjagen. Nicht mal ein kleiner Troll möchte sterben ?gehen. Na dann setz Ich mich mal hier auf die Friedhofsbank und geniesse die Ruhe. Ach ja ! Meine Froschpillen werden langsam knapp. [Woko° in dag°]
Moin, zu meinen derzeitigen Experimenten ("Ich will, daß _alle_ Dateinamen kortrekt laufen"):
Ich will nicht mv'en sondern cp'en :-)
Meines Wissens gibt es in perl zwar "rename" als Äquivalent zu "mv", aber nix für "cp". Ich habe "File::Copy" angeguckt. Läuft bei mir nicht, was aber egal ist: Es kann ohnehin nicht kopieren unter Beibehaltung des original-Zeitstempels.
David Haller:
Schalt ein 'touch -a -r ORIGINAL KOPIE' dahinter...
Das würde das Problem nicht lösen. Ausgangsproblem: Ich habe "kranke" Dateinamen, die ich aus perl der Shell übergebe. Vorschlag hier: Mach es nicht über die Shell, nimm eine perl-interne-Funktion Widerspruch von mir: Gibt es nur für "move", nicht für "copy". Idee von dir: Touchen der Kopie über die Shell. Womit wir wiedr beim Ausgangsproblem wären: Wie erzeuge ich bombensichere Dateinamen.
Alternativen gerne gehört. Irgendwas in der Art von "Kopiere::Gnadenlos" :-)
Teste mal mit folgendem:
Danke, werde ich machen.
Achso: Woher kommen nochmal die kranken Dateinamen? Sind das schon vorhandene (und wenn ja, auf welchem FS?) oder liest du die erst aus den Dateien aus?
Es werden, grob gesagt, Fontdateien so umbenannt, daß sie "richtig" heissen, also nicht mehr "ARIALBI.TTF" sondern "Arial Bold Italic.ttf". Es gibt aber Fonts, die heissen "Sabon*Light" mit Sternchen drin. Das Programm ist unterteilt in Subroutinen, die in perl mit "require" eingebunden werden und ein Hauptprogramm. Ich werde in meinemn Hauptprogramm solche Dateinamen filtern. Ich möchte aber, daß die Subroutinen prinzipiell korrekt mit allen Dateinamen umgehen können, damit andere Coder nicht ins Messer laufen. Man kann keinen Designer davon abhalten, seinen Font "~/*" zu nennen. :-)
PS: Wer kranke Dateinamen verwendet, erlaubt oder in Umlauf bringt...
Voll korrekt. Allerdings interessiert mich das Thema generell mal. Zum Beispiel, um Daten auf einem Linux-Fileserver zu backuppen, die per netatalk oder Samba erzeugt wurden. Usererziehung kann man sowieso knicken. Nicht in dieser Welt. Und dann ist es noch interessant für die cgi-Programmierung. Vor einiger Zeit gab es hier einen Thread zum Thema suidperl, in dem gezeigt wurde, wie schnell einem da was "untergeschoben" werden kann. Wäre generell nicht schlecht, wenn man eine Funktion "mach_sicher($filename)" in der Schublade hat. Gruß, Ratti -- http://www.gesindel.de | Fontlinge | Die Schriftenverwaltung für Windows
Hallo Ratti, * ratti schrieb am 18.Jun.2002:
Man kann keinen Designer davon abhalten, seinen Font "~/*" zu nennen. :-)
Doch der Kernel. Ich wiederhole nochmal. Es ist nicht möglich, daß sich in einem Dateiname ein / befindet. Völlig egal, ob Du das in bash, ksh, csh, tcsh, zsh, perl, php, C, C++, Java, fortran, pascal, eifel, assembler oder was auch immer machst. Es geht nicht. Nimm doch einfach mv $OLDFILENAME $NEWFILENAME oder cp $FILENAME $NEWFILENAME Damit kann in den Variablen stehen, was will. Es wird gemacht. Solange im Name der Variable nichts mekrwürdiges steht, brauchst Du nicht zu maskieren. Der Inhalt der Variable ist egal, die bash wertet nur einmal aus. Aber das habe ich Dir schon mal dagelegt. Bernd -- ROTFL = Rolling On The Floor, Laughing = Auf dem Boden wälzen, lachend. SCNR = Sorry, Could Not Resist = Sorry, Ich konte nicht wiederstehen. AFAIK = As Far As I Know = So weit ich weis|BTW = By The Way = Nebenbei bemerkt IMHO = In My Humble Opinion = meiner bescheidenen Meinung nach |Zufallssig. 9
Moin, Ratti:
Man kann keinen Designer davon abhalten, seinen Font "~/*" zu nennen. :-)
Bernd Brodesser:
Doch der Kernel. Ich wiederhole nochmal. Es ist nicht möglich, daß sich in einem Dateiname ein / befindet. Völlig egal, ob Du das in bash, ksh, csh, tcsh, zsh, perl, php, C, C++, Java, fortran, pascal, eifel, assembler oder was auch immer machst. Es geht nicht.
Mißverständniss: "Seinen Font ~/* nennen" ist nicht "Seine Fontdatei ~/* nennen". Der Fontname ist z.B. "Arial Bold Italic". Der Dateiname ist "ARIALBI.TTF". Da ich gedenke, die Datei wie den Font zu nennen, ergäbe sich bei obigem Beispiel mv ALTER_NAME_DER_DATEI.TTF ~/*.ttf was gut Schaden anrichten kann. Also muß ich die Dateinamen absichern. Ich will ja keine "/" im Dateinamen unterbringen, die müssen dann eben raus. Ich war auf der Suche nach einer Funktion, die "machbare, aber hässliche" Dateinamen umgänglich macht. Ein "*" beispielsweise ist ja legal.
Nimm doch einfach mv $OLDFILENAME $NEWFILENAME oder cp $FILENAME $NEWFILENAME
Damit kann in den Variablen stehen, was will. Es wird gemacht. Solange im Name der Variable nichts mekrwürdiges steht, brauchst Du nicht zu maskieren. Der Inhalt der Variable ist egal, die bash wertet nur einmal aus. Aber das habe ich Dir schon mal dagelegt.
Ich komme aber aus perl, wo ich die Fontnamen auslese. Deswegen kann es zu einer doppelten Substitution kommen. Erst wertet perl aus, dann übergibt er an die bash, die wertet wieder aus. #!/usr/bin/perl $font ="ARIALBI.TTF"; $neu_name =&fontname($font); `mv $font $neu_name.ttf`; Die erste Substitution führt perl durch: `mv $font $neu_name.ttf` wird zu mv ARIALBI.TTF Arial Bold Italic.ttf Das ist bereits falsch - die Spaces gehören da nicht hin. Gar nicht daran zu denken, es käme "*" oder sowas vor. Auch ein " rettet mich nicht. Wenn der Font 12"-Nagel heisst, generiere ich bereits in perl aus `mv "$font" "$neu_name.ttf"`; den Ausdruck mv "NAGEL.TTF" "12"-Nagel.ttf" was ebenfalls syntaktisch falsch ist. Ich bräuchte also sowas: #!/usr/bin/perl $font ="ARIALBI.TTF"; $neu_name =&fontname($font); $befehl ="mv ".&sicherer_dateiname($font). " ".&sicherer_dateiname("$neu_name.ttf"); `$befehl`; Gesucht wird die fiktive funktion "sicherer_dateiname()", die beispielsweise aus folgende konversion ausführt: Arial Bold Italic zu Arial\ Bold\ Italic Sabon*Bold zu Sabon\*Bold oder, deinen Einwurf betreffend: Courier/Italic zu Courier_Italic (Weil: "/" geht nicht, wie du ja auch sagst) Resultat: mv NAGEL.TTF 12\"-Nagel.ttf Die Datei heisst dann also 12"-Nagel.ttf Im Grunde genommen brauche ich also eine simple RE - ich kenne nur einfach nicht alle Zeichen, die unter der Shell Sonderzeichen sind. Sprich: _ ist OK, * muß gequotet werden, ... Solange ich keine verlässlich komplette Sonderzeichenliste habe, kann ich das also nicht programmieren. Und für Google fehlen mir die Suchbegriffe, ich kann ja schlecht nach "* \ / ~ $" suchen, und "quote" ist auch nicht so selten. :-) Ich habe neulich ja schon ein Codefragment bekommen. Ehrlich gesagt, ein Tipp, wo alle Sonderzeichen gelistet sind, würde mich glücklicher machen, weil ich dann auch gleich mitkriege, was es gibt. Aber es geht gut voran. Sieht so aus, als könnte ich bald meine Signatur ändern auf "http://www.gesindel.de | Fontlinge | Die Schriftenverwaltung für LINUX" ;-))) Auf dem Weg zum nützlichen Mitglied der Gesellschaft: Gruß, Ratti -- http://www.gesindel.de | Fontlinge | Die Schriftenverwaltung für Windows
Hallo! Am 20 Jun 2002 23:53:06 +0200 schrieb ratti:
Aber es geht gut voran. Sieht so aus, als könnte ich bald meine Signatur ändern auf "http://www.gesindel.de | Fontlinge | Die Schriftenverwaltung für LINUX" ;-)))
Und am Besten Deinen Nickname gleich mit 8:-) uuuuaaaahhhhhhh SCNR -- Gruß Andreas Meyer http://home.wtal.de/MeineHomepage
Moin, ratti schrieb am 20.06.2002 (23:53):
Im Grunde genommen brauche ich also eine simple RE - ich kenne nur einfach nicht alle Zeichen, die unter der Shell Sonderzeichen sind. Sprich: _ ist OK, * muß gequotet werden, ...
Solange ich keine verlässlich komplette Sonderzeichenliste habe, kann ich das also nicht programmieren. Und für Google fehlen mir die Suchbegriffe, ich kann ja schlecht nach "* \ / ~ $" suchen, und "quote" ist auch nicht so selten. :-)
Eventuell könnte bei einigen Treffern der Anfrage "bash Sonderzeichen maskieren/quoten" oder so ähnlich was dabei sein.
Ich habe neulich ja schon ein Codefragment bekommen. Ehrlich gesagt, ein Tipp, wo alle Sonderzeichen gelistet sind, würde mich glücklicher machen, weil ich dann auch gleich mitkriege, was es gibt.
Ich habe mal in meinem schlauen Buch[1] gesucht und für die bourne-shell folgende Tabelle gefunden. Im Kapitel über die bash steht "Das Quoting der bash entspricht weitgehend dem Quoting der Bourne-shell. Neben der Kommandosubstitution der Bourne-Shell `kommando` wird jedoch auch die neu hinzugekommene Kommandosubstitution $(kommando) innerhalb von "..." ausgewertet." Man möge mir das html verzeihen, ich bin kein großer Ascii-Grafiker. Ich hoffe mal, daß es durch den Attachmentcutter durchkommt. Gruß, Antje [1] Helmut Herold: Unix-Shells (Addison-Wesley, 2. Aufl.1996), Seite 88 -- 'The Geek shall inherit the earth.' - Linus 5:5
ratti wrote:
Ein "*" beispielsweise ist ja legal.
Aber nervig.
Ich bräuchte also sowas:
#!/usr/bin/perl $font ="ARIALBI.TTF"; $neu_name =&fontname($font); $befehl ="mv ".&sicherer_dateiname($font). " ".&sicherer_dateiname("$neu_name.ttf");
`$befehl`;
Ich wuerde den Dateinamen durch 2 regexes jagen: "[^a-zA-Z0-9+.!~%_-]" -> "-" und "-+" -> "-" und den String in '' einpacken. Es muss ja nicht 100% mit dem Fontnamen uebereinstimmen, oder? Peter
Hallo Ratti, hallo Leute, Am Donnerstag, 20. Juni 2002 23:53 schrieb ratti:
Ratti:
Man kann keinen Designer davon abhalten, seinen Font "~/*" zu nennen.
Da ich gedenke, die Datei wie den Font zu nennen, ergäbe sich bei obigem Beispiel mv ALTER_NAME_DER_DATEI.TTF ~/*.ttf was gut Schaden anrichten kann. Also muß ich die Dateinamen absichern.
Ich will ja keine "/" im Dateinamen unterbringen, die müssen dann eben raus. Ich war auf der Suche nach einer Funktion, die "machbare, aber hässliche" Dateinamen umgänglich macht. Ein "*" beispielsweise ist ja legal.
Ich komme aber aus perl, wo ich die Fontnamen auslese. Deswegen kann es zu einer doppelten Substitution kommen. Erst wertet perl aus, dann übergibt er an die bash, die wertet wieder aus.
#!/usr/bin/perl $font ="ARIALBI.TTF"; $neu_name =&fontname($font); `mv $font $neu_name.ttf`;
Die erste Substitution führt perl durch: `mv $font $neu_name.ttf` wird zu mv ARIALBI.TTF Arial Bold Italic.ttf
Das ist bereits falsch - die Spaces gehören da nicht hin. Gar nicht daran zu denken, es käme "*" oder sowas vor.
Auch ein " rettet mich nicht. Wenn der Font 12"-Nagel heisst, generiere ich bereits in perl aus [...] den Ausdruck mv "NAGEL.TTF" "12"-Nagel.ttf" was ebenfalls syntaktisch falsch ist.
Setze die Dateinamen in einfache Anführungszeichen ' (= Apostroph/Hochkomma) Das beseitigt AFAIK fast alle Probleme mit Sonderzeichen [1] bis auf - einfache Anführungszeichen -> mit \' maskieren - / (ist und bleibt ein Pfadtrenner) - \0 (wobei es mich überraschen würde, wenn das in einem Fontname vorkommt ;-) \0 ist allerdings ungetestet, da ich noch nicht herausbekommen habe, wie ich mit touch eine Datei anlege, die \0 im Namen hat. (sachdienliche Hinweise willkommen) Keine Ahnung, ob Perl die Variablen noch ersetzt, wenn Du ` mv '$font' '$neu_name.ttf' ` machst. Falls nicht, verwende eben [2]: $command = "mv '" . $font . "' '" . $neu_name . ".ttf'" `$command`
Gesucht wird die fiktive funktion "sicherer_dateiname()", die
*g* Die kannst Du haben - lass einfach nur [-.a-zA-Z0-9_] durch und ersetze den Rest durch _ - wer sich daran stört, verwendet eben "falsche" Dateinamen ;-) Im Ernst: Wenn Du mit einfachen Anführungszeichen arbeitest, reduziert sich die Anzahl der problematischen Sonderzeichen sehr (siehe oben).
Aber es geht gut voran. Sieht so aus, als könnte ich bald meine Signatur ändern auf "http://www.gesindel.de | Fontlinge | Die Schriftenverwaltung für LINUX" ;-)))
Wäre schön... (wobei mich das daran erinnert, dass die Windows-Version bei mir schon seit längerem ungetestet auf der Platte liegt ;-) Hast Du eigentlich schon die Generierung der Vorschaubilder fertig? Falls nicht, kannst Du vielleicht bei kfontinstaller ein wenig abschreiben ;-) Gruß Christian Boltz [1] siehe auch die Tabelle von Antje. [2] Da ich immer noch nicht dazu gekommen bin, mich in Perl einzuarbeiten, gehe ich mal davon aus, dass der . (Punkt) ebenso wie z. B. bei PHP dazu dient, Zeichenketten zu verbinden. Falls das nicht stimmt, den . durch den richtigen Operator für "Zeichenfolgen verketten" ersetzen. -- Registrierter Linux-Nutzer #239431 Linux - life is too short for reboots.
* Christian Boltz schrieb am 21.Jun.2002:
Am Donnerstag, 20. Juni 2002 23:53 schrieb ratti:
- einfache Anführungszeichen -> mit \' maskieren - / (ist und bleibt ein Pfadtrenner)
ACK
- \0 (wobei es mich überraschen würde, wenn das in einem Fontname vorkommt ;-) \0 ist allerdings ungetestet, da ich noch nicht herausbekommen habe, wie ich mit touch eine Datei anlege, die \0 im Namen hat. (sachdienliche Hinweise willkommen)
Wenn Du mit \0 die ASCII NUL meinst und nicht die Zeichen Backslash und die Ziffer 0, dann geht dies genausowenig wie der /. \0 ist das Zeichen, daß der Name hier zu Ende ist. Wenn Deine Datei etwa datei heißt, so steht in Deinem Verzeichniß die Adresse zur I-node der Datei und dann der Name der Datei, der mit \0 abgeschlossen wird. Hier also datei\0 Bernd -- Welches Buch ist zu empfehlen? Schon mal bei SuSE vorbeigesehen? http://www.suse.de/de/products/books/index.html oder die Empfehlungen der SuSE-Entwickler auf dem eigenen Rechner? file:///usr/share/doc/sdb/de/html/literatur.html |Zufallssignatur 5
Hallo, Christian Boltz:
Im Ernst: Wenn Du mit einfachen Anführungszeichen arbeitest, reduziert sich die Anzahl der problematischen Sonderzeichen sehr (siehe oben).
Das ist zwar nicht so ganz das, was ich gesucht hatte, kommt dem aber wohl am nächsten.
Aber es geht gut voran. Sieht so aus, als könnte ich bald meine Signatur ändern auf "http://www.gesindel.de | Fontlinge | Die Schriftenverwaltung für LINUX" ;-)))
Wäre schön... (wobei mich das daran erinnert, dass die Windows-Version bei mir schon seit längerem ungetestet auf der Platte liegt ;-)
Vergiss den Mist. ;-) Da alles in VisualBasic programmiert war, mußte ich komplett von vorne beginnen, kannte aber schon die Probleme, die ich damals nie eingeplant hatte. Diesmal habe ich von vorherein auch Postscriptfonts im Hinterkopf gehabt, sprich: 1 Font muß nicht unbedingt 1 File sein. Alles wird besser. ;-)
Hast Du eigentlich schon die Generierung der Vorschaubilder fertig? Falls nicht, kannst Du vielleicht bei kfontinstaller ein wenig abschreiben ;-)
Schon laaaange. Seit vorgestern. ;-) Geht fabelhaft über die Perl-Module von ImageMagic: sub create_image { my $filename = shift(@_); my $base; my $path; my $type; my $image; ($base,$path,$type) = fileparse($filename, qr{\..*}); $image = Image::Magick->new; $image->Set(size=>'500x50'); $image->ReadImage('xc:white'); $image->Annotate(x=> 0, y=>40, font=>$filename, pointsize=>40, fill=>'black', text=>'Fontlinge äöüß'); $image->Write("$path$base.png"); } So einfach kann das Leben sein. Gruß, Ratti -- http://www.gesindel.de | Fontlinge | Die Schriftenverwaltung für Windows
On Thu, 2002-06-13 at 22:47, ratti wrote:
Da ich nix schlaueres gefunden habe, verwende ich also derzeit in perl:
`cp "$alter_name" "$neuer_name" -a`;
Schau Dir mal perldoc -f quotemeta an. print quotemeta 'hsakjfh kjfsah! kjasdh fkj*'; -> hsakjfh\ kjfsah\!\ kjasdh\ fkj\* Vielleicht hilfts ;-) Volker -- Volker Kroll 4mino AG Chief System Developer Chausseestr. 52 b volker.kroll@4mino.de D-10115 Berlin Tel.: +49-30-2888490-0 Fax.: +49-30-2888490-99
Hallo Ratti, * ratti schrieb am 13.Jun.2002:
Es sieht aus, als müsse ich mir da eine RE selber basteln. 8:-( Eigentlich fühle ich mich dafür gar nicht sicher genug. Gibt es irgendwo eine Liste aller "relevanten" Zeichen, die in sowas wie `mv $a $b` nicht vorkommen dürfen? Mir fällt dazu jetzt ein:
* ? [ ] { } > < | " ` ' ' ~ ...ohje, das ist ja fast alles zwischen ASCII 33 und 64.
Wieso sollen die da nicht vorkommen dürfen? Die dürfen alle als Inhalt der Variable vorkommen. Nicht direkt, das ist allerdings richtig. Aber das willst Du offensichtlich auch nicht. Aber als Inhalt der Variablen darf jedes Zeichen vorkommen, und es wird so genommen, wie es ist. Die `..` um das mv ergeben aber keinen rechten Sinn. `..` Bedeutet, ersetze die `..` mitsamt des Inhaltes durch die Ausgabe des Befehls, der innerhalb der `..` steht. Etwa a=`ls` Hierbei wird der Variablen a die Ausgabe von ls zugewiesen. mv hat aber gar keine Ausgabe, deshalb wird das `...` auch nur durch eine Leerzeile ersetzt. Der Effekt von mv bleibt natürlich erhalten.
Was mich wundert: Ich hatte eigentlich eine Fehlermeldung erwartet, wenn ich das hier machen:
touch a\"b # Datei erzeugen die heisst a"b
Und wieso? Der \ deckt doch das " ab. " hat doch nur in der Shell eine besondere bedeutung, nicht in mv, cp oder touch. Die Shell, die läuft interpretiert den \ und weiß, daß das nächste Zeichen so genommen wird, wie es da steht, es übergibt somit die Zeichenkette a"b an touch. touch interpretiert nicht am Namen herum, sondern nimmt es so wie es ist. Jeden Namen, alles, auch ein \ würde so genommen wie es ist. Aber den \ bekommt touch erst gar nicht zu Gesicht. Den verwurschtelt schon die Shell. Die Shell macht aus a\"b ein a"b und übergibt touch dieses a"b. Und touch legt eine Datei namens a"b an.
...und dann ein Script starte, das so aussieht:
a=`find ./ -name "a*"` echo $a mv "$a" "safename"
Ich hatte erwartet,
mv "$a" "safename" würde expandiert zu mv "a"b" "safename" und somit eine Fehlermeldung verursachen...
Nein, nein. Es wird nur einmal expandiert. "$a" wird mit dem Inhalt von $a ersetzt. Dieser Inhalt wird aber so wie er ist an dem Befehl weitergegeben. Der Befehl selber interpretiert nicht. Was anderes ist folgendes: Du kanst auch sowas machen: mv "$a" "$a.test" da wird dann einfach jeder Datei ein test angehangen. Hier mußt Du vorsichtig sein, wenn da nicht test stände, sondern etwa t\l oder so. Also: mv "$a" "$a.t\l" Denn wird der \ hier interpretiert. Aber die Variable wird so genommen, wie sie ist.
Verdammt! Immer wenn man denkt, man hätte es kapiert! =%-)
Es expandiert nur die Shell. Und nur einmal. Wenn Du es öfters haben möchtest, muß Du ein eval davor setzen. $ a='$b' $ b=test $ echo $a $b $ echo $b test $ eval echo $a test Die Befehle interpretieren normalerweise nicht nochmal. Außnahme ist hier etwa find. Beim find wird das was nach -name kommt so interpretiert, wie es auch die shell machen würde. Daher sollte auch in einem find das was nach -name kommt, in '...' gesetzt werden, damit die Shell es nicht schon vorher interpretiert. Ein grep interpretiert das 1.Argument nach den Options z.B als Suchmuster. Aber da hat der * eine ganz andere Bedeutung als in der Shell. In der Shell steht der * für beliebig viele beliebige Zeichen. Bei grep und anderen RegExp steht der * für beliebig häufige Wiederhohlung des letzten Zeichens. Aber auch hier sollte der Suchbegriff in '...' eingeschlossen werde, damit die Shell ein evtl. * nicht interpretiert. Das Problem, daß Du mit mv in Deiner letzten Mail hattes, ist kein Shell und Expansionsproblem. Du hattest versucht eine Datei einen Namen zu geben, der ein / enthält. Das funktioniert grundsätzlich nicht. Aber da hat die Shell nichts mit zu tun. Die Shell hat die Variable brav expandiert und es an mv übergeben. In dem Argument von mv kam aber ein / vor. mv interessiert sich auch nicht sonderlich dafür, sondern macht einfach einen Systemaufruf rename und übergibt die beiden Argumente. Nun aber tritt der Kernel himself in Kraft und verweigert die Anlegung eines Dateinamens, der ein / enthält. Du kanst Dich auf dem Kopf stellen, und mit den Füßen wackeln, aber Du wirst es nicht schaffen, eine Datei einen Namen zu geben, der einen / enthält, weil der Kernel es verweigert. Der Ersetzungsmechanismus der Shell: Die Shell ersetzt ein * durch beliebig viele, beliebige Zeichen. Aber immer nur so, daß sich Dateinamen aus dem aktuellen Verzeichnis ergeben. Steht im Verzeichnis etwa datei, datei1 und test, so macht die shell aus d* datei datei1 und aus *e* macht die shell datei datei1 test Daneben gibt es noch ? und {...} Konstrukte. $VARIABLE wird durch den Inhalt von VARIABLE ersetzt. Hier gibt es noch eine Reihe wunderschöner Möglichkeiten, etwa ${VARIABLE:-Wert} Wird durch den Inhalt der Variable VARIABLE ersetzt. Wenn sie aber leer ist, dann wird es mit Wert ersetzt. \ nimmt die Sonderbedeutung des nächsten Zeichens für die Shell weg. So wird \$ mit $ ersetzt, und nicht das nächste Wort als Variable interpretiert. \\ steht somit für das \ selbst. "..." innerhalb der "..." werden alle * und ? nicht expandiert. Es ist so, als stände vor jedem * und jedem ? ein \. Ebenfalls werden die ' nicht expandiert. Wohl aber werden die ` und die $ expandiert. Variablen innerhalb von "..." werden somit ersetzt. '...' innerhalb der '...' wird schier gar nichts expandiert, weder * und ? noch $ noch " oder ` noch nicht mal das \ wird expandiert. `...` alles was innerhalb der `...` steht wird als Befehl aufgefaßt und ausgeführt. Danach wird `...` durch die Ausgabe des Befehls ersetzt. Mit Ausgabe ist NB die Standardausgabe und nicht die Standardfehlerausgabe gemeint. Wie auch immer ersetzt wird. Es wird nur einmal ersetzt. Das Ergebnis wird dann genommen. Es wird nicht nochmal interpretiert. Es sei denn, es stände ein eval davor. Ist natürlich alles andere als Vollständig, soll nur was das Verständnis fördern. Und nochmal, die einzelnen Befehle, wie mv, cp, rm, touch, cat, sort ... expandieren nicht. Wenn bei denen sowas wie a*b ankommt, dann nehmen sie es auch so. Bernd
participants (9)
-
Andreas Meyer
-
Antje M. Bendrich
-
B.Brodesser@t-online.de
-
Christian Boltz
-
David Haller
-
Juergen Schwarting
-
Peter Wiersig
-
ratti
-
Volker Kroll