mein Problem klingt eigentlich sehr simpel:
Ich möchte gerne Listen mit Dateien aus einem Find-Ergebnis erstellen. Die
Form sollte
mTime(als Epoch):Dateiname sein (anderes Trennzeichen möglich)
Naiv formuliert:
find DIR COND -print "%T@:%p\n" > liste.csv
Die Listen werden dann untereinander abgeglichen (welche Datei existiert wo)
und dann ggf. als Parameter für einen rm-Aufruf benutzt.
Da Dateinamen aber "böse" sein können, ist es üblich so etwas über xpath zu
erledogen - hier fehlt mir aber gerade der Ansatz:
Wie schaffe ich es am besten, den Dateinamen in einer csv-Datei abzulegen
und dann mit xargs zu benutzen?
Danke,
Keep smiling
yanosz
mein Problem klingt eigentlich sehr simpel:
Ich möchte gerne Listen mit Dateien aus einem Find-Ergebnis erstellen. Die
Form sollte
mTime(als Epoch):Dateiname sein (anderes Trennzeichen möglich)
Naiv formuliert:
find DIR COND -print "%T@:%p\n" > liste.csv
Die Listen werden dann untereinander abgeglichen (welche Datei existiert wo)
und dann ggf. als Parameter für einen rm-Aufruf benutzt.
Da Dateinamen aber "böse" sein können, ist es üblich so etwas über xargs zu
Da Dateinamen "böse" sein können, ist es nicht möglich, sie in
csv-Dateien abzulegen.
Was bleiben für Alternativen?
* Kodiere die Dateinamen so, dass nichts "Böses" mehr übrig bleibt; dann
kannst du sie in csv-Dateien stecken.
Vorteil: Anschließend ist die Liste sehr gut mit Text-bearbeitenden
Programmen wie "diff", "sort", "uniq" oder "sed" zu bearbeiten.
Nachteil: Um die Dateinamen zu verwenden, d.h. Dateien mit ihnen
anzufassen, muss man sie wieder entsprechend dekodieren.
Leider gibt es nichts Fertiges dafür.
Oder
* verwende ein anderes Dateiformat als csv.
Wenn du die GNU-Fassungen von "find" und "xargs" zur Verfügung hast, dann
kannst du dir so helfen:
$ find DIR COND -printf '%T@\000%p\000' > liste.nul
(Übrigens: Hinter das "-print" muss ein "f".)
Mit "xargs" benutzen kannst Du dann die Liste etwa so:
$ xargs -0 -r -- sh -c \
'while test "$#" -ge 2
do
Zeit="$1" && Name="$2" && shift 2 && ...
done' sh < liste.nul
oder, falls man lieber direkt ein Programm für jede Datei aufrufen will,
anstatt im Shell eine Schleife über die positional Parameters
abzuarbeiten:
$ xargs -0 -r -n 2 -- ... < liste.nul
Die GNU-Fassung von "sort" kann mit NUL als Feld-Trennzeichen und als
Zeilenende umgehen (Options "-t" bzw. "--zero-terminated"). "grep" kennt
"--null" und "--null-data". Bei "diff" und "uniq" gibt es leider nichts
dieser Art.
--
Wer mir E-Mail schreiben will, stelle | When writing me e-mail, please
bitte vor meine E-Mail-Adresse meinen | precede my e-mail address with
Vor- und Nachnamen, etwa so: | my full name, like
Helmut Waitzmann <x...@example.net>, (Helmut Waitzmann) x...@example.net
GNU-Find:
find DIR COND -printf '%T@:"%p"\n' > liste.csv
Dann stoeren auch keine : im Dateinamen, und du hast bereits
quote-zeichen fuer die weitere Verarbeitung.
> Die Listen werden dann untereinander abgeglichen (welche Datei existiert wo)
> und dann ggf. als Parameter für einen rm-Aufruf benutzt.
> Da Dateinamen aber "böse" sein können, ist es üblich so etwas über xargs zu
> erledogen - hier fehlt mir aber gerade der Ansatz:
> Wie schaffe ich es am besten, den Dateinamen in einer csv-Datei abzulegen
> und dann mit xargs zu benutzen?
Wenn die CSV-Datei wie oben geformt ist, indem du eine Zeile
durch sed jagst:
... | sed 's/^[0-9]*://' | xargs rm --
Das -- beim rm sorgt dafuer, dass Dateinamen, die mit - anfangen nicht
als Option interpretiert werden.
Juergen
--
Juergen P. Meier - "This World is about to be Destroyed!"
end
If you think technology can solve your problems you don't understand
technology and you don't understand your problems. (Bruce Schneier)
> Da Dateinamen "böse" sein können, ist es nicht möglich, sie in
> csv-Dateien abzulegen.
Naja man könnte folgendes Konstrukt für die Dateinamen verwenden:
-------" Böser Text - Beispiel "
norbert@nolin:~> cat text.txt
N.o,rbert Mön-djen
-------" Umkodieren nach base64 "
norbert@nolin:~> recode ../b64 < text.txt > text.b64
-------" So sieht es dann aus "
norbert@nolin:~> cat text.b64
Ti5vLHJiZXJ0IE3Dtm4tZGplbgo=
-------" und wieder zurück "
norbert@nolin:~> cat text.b64 | recode /64..
N.o,rbert Mön-djen
ich würde also vorschlagen die Dateinamen durch recode ../b64 zu pipen und dann abzulegen. Anschließend kann man wieder alle Verdächtigen zur Manipulation verwenden. Dann für rm durch recode /b64.. "zurückpipen".
Allerdings wird das wohl mit Bordmitteln von find nicht direkt was werden. Wird dann wohl eher was in Form von find -exec script \{\} \;
Oder auch sowas (eine Zeile):
find . | (while read f ; do echo -n "`date +%s` , " ; echo "$f" | recode ../b64 ; done )
Ciao Nobbe
> Helmut Waitzmann wrote:
>
>> Da Dateinamen "böse" sein können, ist es nicht möglich, sie in
>> csv-Dateien abzulegen.
> [...]
> find . | (while read f ; do echo -n "`date +%s` , " ; echo "$f" | recode ../b64 ; done )
Dieser Code funktioniert mindestens mit Dateinamen, die ein Newline
oder Backslash enthalten, nicht.
Naja, war ja auch eher ein Gedankenkonzept. Inhaltlich ausbauen darf es dann der Frager schon selbst. Man könnte das find ja noch mit printf parameter dazu bringen /0 als Zeilenende zu schicken. Und dann IFS noch entsprechend anpassen. Aber wie gesagt, es ging mir nur darum zu zeigen das man die Dateinamen reversibel umkodieren kann um sie weiterzuverarbeiten. Wobei ich ehrlich gesagt meine das sowas wie Backslash oder Newline nur als Unfall in einen Dateinamen kommen sollten.
OK, Mist jetzt bekomme ich Dresche.
Ciao Nobbe
Ich wollte ja auch nur darauf hinweisen, dass dieser Code nicht einfach
so übernommen werden sollte.
> [...]
> Wobei ich ehrlich gesagt meine das sowas wie Backslash oder Newline
> nur als Unfall in einen Dateinamen kommen sollten.
Wenn jemand von "bösen" Dateinamen spricht, denke ich an untrusted
Input, und da muss man mit allem rechnen, was theoretisch möglich ist.
>$ find DIR COND -printf '%T@\000%p\000' > liste.nul
>(Übrigens: Hinter das "-print" muss ein "f".)
>Mit "xargs" benutzen kannst Du dann die Liste etwa so:
>$ xargs -0 -r -- sh -c \
Da besteht das Problem, dass man nicht sicherstellen kann, dass
xargs das sh immer mit unzerteilten Paaren (Zeitstempel,
Dateipfad) aufruft; z.B. ist es möglich, dass nach 1249 Paaren
gerade noch Platz in der Parameterliste ist für den nächsten
Zeitstempel und der dazugehörende Dateipfad nicht mehr mit
hineinpasst.
>oder, falls man lieber direkt ein Programm für jede Datei aufrufen will,
>anstatt im Shell eine Schleife über die positional Parameters
>abzuarbeiten:
>$ xargs -0 -r -n 2 -- ... < liste.nul
Und hier würde ich xargs noch das Option -x dazugeben, damit es
immer und nicht nur maximal zwei Zeichenketten (d.h. Zeitstempel
und Dateipfad) an das von ihm gestartete Programm übergibt.
(Wenn das mal nicht geht, weil der Dateipfad so lang ist, dass
die Parameterlist zu lang würde, bricht xargs wenigstens mit
einem Fehler ab).
--
Bitte in die Adressierung auch meinen |Please put my full name also into
Vor- u. Nachnamen stellen z.B. |the recipient like
Friedhelm Waitzmann <xxx@example>, (Friedhelm Waitzmann) xxx@example,
"Waitzmann, Friedhelm" <xxx@example>
>> Wobei ich ehrlich gesagt meine das sowas wie Backslash oder Newline
>> nur als Unfall in einen Dateinamen kommen sollten.
>
> Wenn jemand von "bösen" Dateinamen spricht, denke ich an untrusted
> Input, und da muss man mit allem rechnen, was theoretisch möglich
> ist.
Hmm, eigentlich müßte dieses Konstrukt doch damit umgehen können.
[ GNU bash, version 3.2.39(1)-release (i586-suse-linux-gnu) ]
Oder habe ich da immer noch was übersehen? ich habe kaum
exotische Dateinamen zur Hand. Und bei den exotischen die ich
zum Test generiere vergesse ich bestimmt wieder was. Ein
schneller Test in der Konsole ergab nichts nachteiliges. :-)
find . -print0 | ( while read -r -d\0 f ; do echo $f ; done )
Ciao Nobbe
> Hmm, eigentlich müßte dieses Konstrukt doch damit umgehen können.
> [ GNU bash, version 3.2.39(1)-release (i586-suse-linux-gnu) ]
> Oder habe ich da immer noch was übersehen? ich habe kaum
> exotische Dateinamen zur Hand. Und bei den exotischen die ich
> zum Test generiere vergesse ich bestimmt wieder was. Ein
> schneller Test in der Konsole ergab nichts nachteiliges. :-)
>
> find . -print0 | ( while read -r -d\0 f ; do echo $f ; done )
Das wird schon mal funktionieren, ist aber nicht garantiert.
Der Input von 'read' ist als 'text file' definiert. Damit gibt es Dinge
wie maximale Zeilenlänge (über die man erst stolpert, wenn es besonders
weh tut) und undefiniertes Verhalten bei \0 (das der read der Bash zwar
hinbekommt, was aber nirgendwo festgeschrieben ist).
Und so wie das echo-Kommando bei Dir geschrieben ist, wird es jede Folge
von White Space zu einem einzigen Leerzeichen komprimieren und nicht das
Original ausgeben. Führende Leerzeichen fehlen ganz und Backslashes
werden gewandelt.
> Norbert Möndjen <N.Moe...@vodafone.de> writes:
>> find . -print0 | ( while read -r -d\0 f ; do echo $f ; done )
>
> Das wird schon mal funktionieren, ist aber nicht garantiert.
>
> Der Input von 'read' ist als 'text file' definiert. Damit gibt es
> Dinge wie maximale Zeilenlänge (über die man erst stolpert, wenn es
> besonders weh tut) und undefiniertes Verhalten bei \0 (das der read
> der Bash zwar hinbekommt, was aber nirgendwo festgeschrieben ist).
Funktioniert noch an an paar anderen Stellen nicht, wie ich mit Bedauern feststellen mußte.
>
> Und so wie das echo-Kommando bei Dir geschrieben ist, wird es jede
> Folge von White Space zu einem einzigen Leerzeichen komprimieren und
> nicht das
> Original ausgeben. Führende Leerzeichen fehlen ganz und Backslashes
> werden gewandelt.
Das mit dem echo war mir klar, sollte auch nur für einen beliebigen
Befehl stehen. mit -E sollte man das aber, denke ich mal, in den
Griff bekommen.
Aber es geht ja noch weiter in diesem Spiel. Wenn man tatsächlich die
Filenamen + zusätzliche Infos wie Erstellungsdatum weiter verarbeiten will wird das ganze beliebig schwierig. Will ich das ganze in ein File
schreiben um es weiter zu verarbeiten dann brauche ich ja zwingend Column und Row Seperatoren. Eigentlich bleibt mir aber nur die "NULL".
Row-Seperator dann eine Kombo NULL+LF und für die Columns NULL+Komma? Und welche Programme kommen dann damit noch zurecht? Also das ist dann
der Punkt an dem man sich vom Scripting verabschiedet und nach einer
Programmiersprache ausschau hält.
Da fällt mir natürlich noch eine Frage ein: Wie bekomme ich am besten und am Shell-konformsten ein Nullbyte? Also wenn ich z.B. einen Fieldseperator definieren muß, wie bei awk z.B., \0 funktioniert ja nicht immer.
Ciao Nobbe
>Jan Luehr <use...@stephan.homeunix.net>:
>> mein Problem klingt eigentlich sehr simpel:
>> Ich möchte gerne Listen mit Dateien aus einem Find-Ergebnis erstellen. Die
>> Form sollte
>> mTime(als Epoch):Dateiname sein (anderes Trennzeichen möglich)
>> Naiv formuliert:
>> find DIR COND -print "%T@:%p\n" > liste.csv
>
>GNU-Find:
> find DIR COND -printf '%T@:"%p"\n' > liste.csv
>
>Dann stoeren auch keine : im Dateinamen, und du hast bereits
>quote-zeichen fuer die weitere Verarbeitung.
Und wenn jetzt in einem Dateinamen ein Anführungszeichen vorkommt?
> Heike C. Zimmerer wrote:
>
>> Norbert Möndjen <N.Moe...@vodafone.de> writes:
>>> find . -print0 | ( while read -r -d\0 f ; do echo $f ; done )
>>
>>
>> Und so wie das echo-Kommando bei Dir geschrieben ist, wird es jede
>> Folge von White Space zu einem einzigen Leerzeichen komprimieren und
>> nicht das
>> Original ausgeben. Führende Leerzeichen fehlen ganz und Backslashes
>> werden gewandelt.
>
> Das mit dem echo war mir klar, sollte auch nur für einen beliebigen
> Befehl stehen. mit -E sollte man das aber, denke ich mal, in den
> Griff bekommen.
Nein. Das Hauptproblem im obigen echo-Statement ist das fehlende
Quiting um $f. Beim read ist es das Fehlende IFS= und das fehlende -r.
Echo hat noch mehr Probleme, wenn beispielsweise das Argment mit - und
einem bestimmten Zeichen beginnt. Es lohnt sich nicht, am echo
herumzudoktern. Robust programmiert heißt der echo für beliebige
Argumente »printf '%s\n'« und das Argument muss gequotet sein.
> Da fällt mir natürlich noch eine Frage ein: Wie bekomme ich am besten
> und am Shell-konformsten ein Nullbyte? Also wenn ich z.B. einen
> Fieldseperator definieren muß, wie bei awk z.B., \0 funktioniert ja
> nicht immer.
Du solltest Deine Programme so aufbauen, dass das nicht erforderlich
ist. Die allermeisten Utilities (Builtins und andere) der Shell
erwarten Text-Input. Da lebst Du mit \0 immer gefährlich. Die Methode,
'krummen Text' als base64 durchzuschleusen, solange sein genauer Inhalt
nicht wichtig ist, wurde ja schon gennannt.
>>>> find . -print0 | ( while read -r -d\0 f ; do echo $f ; done )
>>>
>>> Und so wie das echo-Kommando bei Dir geschrieben ist, wird es jede
>>> Folge von White Space zu einem einzigen Leerzeichen komprimieren
>>> und nicht das Original ausgeben. Führende Leerzeichen fehlen ganz
>>> und Backslashes werden gewandelt.
>>
>> Das mit dem echo war mir klar, sollte auch nur für einen beliebigen
>> Befehl stehen. mit -E sollte man das aber, denke ich mal, in den
>> Griff bekommen.
>
> Nein. Das Hauptproblem im obigen echo-Statement ist das fehlende
> Quiting um $f. Beim read ist es das Fehlende IFS=
Das sollte nicht relevant sein, solange das Ergebnis des read in nur
einer einzigen Variablen abgelegt wird. Wenigstens sagt sowohl meine
bash-Manpage als auch SUSv3 m.E. eindeutig, dass in diesem Fall der
komplette Input unverändert in dieser einen Variablen abgelegt wird,
komplett unabhängig von $IFS.
> und das fehlende -r.
Schreiben wir vom gleichen Kommando? Oben steht ein -r.
Bezieht sich das auf das »IFS=«? Das ist selbstverständlich relevant:
$ echo ' Hallo' | (read f; echo "|$f|")
|Hallo|
echo ' Hallo' | (IFS= read f; echo "|$f|")
| Hallo|
Wenn das dort wirklich "eindeutig" so steht wie von Dir behauptet (was
ich bezweifle), solltest Du einen Bug Report gegen die Dokumentation
loslassen. Die erste Variable beginnt immer am ersten Zeichen != IFS.
>>> Das Hauptproblem im obigen echo-Statement ist das fehlende Quiting
>>> um $f. Beim read ist es das Fehlende IFS=
>>
>> Das sollte nicht relevant sein, solange das Ergebnis des read in nur
>> einer einzigen Variablen abgelegt wird. Wenigstens sagt sowohl meine
>> bash-Manpage als auch SUSv3 m.E. eindeutig, dass in diesem Fall der
>> komplette Input unverändert in dieser einen Variablen abgelegt wird,
>> komplett unabhängig von $IFS.
>
> Bezieht sich das auf das »IFS=«? Das ist selbstverständlich
> relevant:
>
> $ echo ' Hallo' | (read f; echo "|$f|")
>|Hallo|
> echo ' Hallo' | (IFS= read f; echo "|$f|")
>| Hallo|
Okay, an führende Whitspaces (bzw. allgemeiner: führende Zeichen aus
$IFS) hatte ich nicht gedacht. Mein Fehler.
Das stimmt nur, solange der Input nicht mit whitespace beginnt:
-------------------
ilse@talaxia:~$ echo ' 1 2' | (read a; echo "$a")
1 2
ilse@talaxia:~$ echo ' 1 2' | (IFS= read a; echo "$a")
1 2
ilse@talaxia:~$
-------------------
Tschuess,
Juergen Ilse (jue...@usenet-verwaltung.de)
--
Ein Domainname (auch wenn er Teil einer Mailadresse ist) ist nur ein Name,
nicht mehr und nicht weniger ...
Und hier nochmal. ich vergesse auch immer die führenden Leerzeichen. :-) So ein Quatsch auch das das erlaubt ist. Dann müßte es doch so machbar sein : (Eine Zeile)
find . -type f -printf "%A@\0%p\0" | ( IFS=$'\0' ; while read -r -d $'\0' t ; do read -r -d $'\0' f ; echo -n "$t , " ; echo -E "$f" | recode ../b64 ; done )
> Heike C. Zimmerer <nospa...@gmx.net> wrote:
>> Norbert Möndjen <N.Moe...@vodafone.de> writes:
>>> Heike C. Zimmerer wrote:
>>>> Norbert Möndjen <N.Moe...@vodafone.de> writes:
>
>>>>> find . -print0 | ( while read -r -d\0 f ; do echo $f ; done )
>>>>
Also ich habe jetzt ein paar Tests gemacht. So wie oben funktioniert es tatsächlich nicht richtig. Aber auf diese Art sollte man einen beliebigen Befehl einen Dateinamen übergeben können. Das $'\0' ist zumindest dokumentiert und nach dem -d muß ein Leerzeichen folgen warum auch immer.
find . -print0 | ( while read -r -d $'\0' f ; do echo -E "$f" ; done )
Und wenn man den Dateinamen dann in einer csv-Datei haben will muß man ihn allerdings umkodieren hier base64. Eine Zeile
find . -type f -printf "%A@ %p\0" | ( IFS=" " ; while read -r -d $'\0' t f ; do echo -n "$t , " ; echo -E "$f" | recode ../b64 ; done )
Man muß hier nur aufpassen das innerhalb der ersten Parameter keine Leerzeichen vorkommen.
So Lösung zum Abschuß freigegeben. :-) Habe ich noch was vergessen?
Ciao Nobbe
Und jetzt nochmal und hoffentlich endgültig. Base64 macht einen Zeilenumbruch nach 76 Zeichen der muß natürlich entfernt werden wenn man das in eine csv-Datei schreben will.
find . -type f -printf "%A@\0%p\0" | ( IFS=$'\0' ; while read -r -d $'\0' t ; do read -r -d $'\0' f ; echo -n "$t , " ; echo -E "$f" | recode ../b64 | tr -d '\n' ;echo ; done ) > text.csv
Ciao Nobbe
Dann hat man bei CSV verloren, denn das Format kennt kein Quoting.
Man muesste dann die dateinamen in eine Kodierung ueberfuehern, die
CSV-Sicher ist, z.B. BASE-64.
Das wuerde aber den Rahmen sprengen.
juergen
Je nach echo wird das aus bereits besagten Gründen fehlschlagen, wenn
eine Datei z.B. '-n' heißt.
Weitere Bedenken habe ich bereits geäußert; ich mochte für meinen Teil
abschließen.
> Norbert Möndjen <N.Moe...@vodafone.de> writes:
>> Und jetzt nochmal und hoffentlich endgültig. Base64 macht einen
>> Zeilenumbruch nach 76 Zeichen der muß natürlich entfernt werden
>> wenn man das in eine csv-Datei schreben will.
>>
>> find . -type f -printf "%A@\0%p\0" | ( IFS=$'\0' ; while read -r -d
>> $'\0' t ; do read -r -d $'\0' f ; echo -n "$t , " ; echo -E "$f" |
>> recode ../b64 | tr -d '\n' ;echo ; done ) > text.csv
>
> Je nach echo wird das aus bereits besagten Gründen fehlschlagen,
> wenn eine Datei z.B. '-n' heißt.
>
> Weitere Bedenken habe ich bereits geäußert; ich mochte für meinen
> Teil abschließen.
Ok, das möchte ich auch respektieren. Dann fällt mir eigentlich nur noch ein echo mit printf zu ersetzen. Es ist einfach ärgerlich das man mit Dateinamen soviel Mühe hat. Bestimmte Dinge hätten einfach verboten gehört. :-)
Ciao Nobbe
>> Und wenn jetzt in einem Dateinamen ein Anführungszeichen vorkommt?
>
> Dann hat man bei CSV verloren, denn das Format kennt kein Quoting.
--($ ~)-- cat test.csv
"""a"""
In der Zelle hatte ich "a" gespeichert.
Bei diesem Format sind sich übrigens OpenOffice.org und Excel 2000
einig.
Michael
Schoen, aber mangels Standard ist das reines Gluecksspiel.
Und was ist mit '""a";"",;a";'? Wie speichern das OO und Exkel?
Und was ist mit zwei solchen Werten in einer Zeile?
Juergen
> Michael Schmarck <usenet-...@schmarck.cn>:
>> Juergen P. Meier <nospa...@jors.net> wrote:
>>> Helmut Waitzmann <Helmut.W...@web.de>:
>>
>>>> Und wenn jetzt in einem Dateinamen ein Anführungszeichen vorkommt?
>>>
>>> Dann hat man bei CSV verloren, denn das Format kennt kein Quoting.
>>
>> --($ ~)-- cat test.csv
>> """a"""
>>
>> In der Zelle hatte ich "a" gespeichert.
>>
>> Bei diesem Format sind sich übrigens OpenOffice.org und Excel 2000
>> einig.
>
> Schoen, aber mangels Standard ist das reines Gluecksspiel.
Tja. Tatsache ist allerdings, das es kein größeres Problem ist,
"a" in einer Zelle zu speichern. Man hat keineswegs "verloren",
denn offensichtlich gibt's ein Quoting. Und von wegen "Glücksspiel":
OOo, Excel und auch Google Docs können eine CSV Datei mit
diesem Inhalt öffnen und importieren sie fehlerfrei.
> Und was ist mit '""a";"",;a";'? Wie speichern das OO und Exkel?
Schau's Dir doch selber an.
--($ ~/.vnc)-- cat ../test.csv
"""""a"";"""",;a"";'"
> Und was ist mit zwei solchen Werten in einer Zeile?
Hm? Was meinst Du damit?
Ich hatte ""a";"",;a";'""a";"",;a";' in der Zelle gespeichert.
--($ ~/.vnc)-- cat ../test.csv
"""""a"";"""",;a"";'""""a"";"""",;a"";'"
Google Docs macht daras:
"""""a"";"""",;a"";'""""a"";"""",;a"";'"
Michael
> Tja. Tatsache ist allerdings, das es kein größeres Problem ist,
> "a" in einer Zelle zu speichern. Man hat keineswegs "verloren",
> denn offensichtlich gibt's ein Quoting.
...welches weit, aber eben leider nicht universell verbreitet ist. Beim
Erstellen stoert das nicht, da kann man sich ja an diese Konvention
halten, aber wenn das Gegenueber sie nicht _lesen_ kann (mir schon
gelegentlich passiert, im Bereich von ERP-Systemen), nuetzt das auch
nicht viel.
Servus,
Stefan
--
http://kontaktinser.at/ - die kostenlose Kontaktboerse fuer Oesterreich
Stefan. Für aparte Stiche in zarten Gewittern!
(Sloganizer)
Norbert Möndjen <N.Moe...@vodafone.de> writes:
>Helmut Waitzmann wrote:
>
>> Da Dateinamen "böse" sein können, ist es nicht möglich, sie in
>> csv-Dateien abzulegen.
>
>Naja man könnte folgendes Konstrukt für die Dateinamen verwenden:
>
>-------" Böser Text - Beispiel "
>norbert@nolin:~> cat text.txt
>N.o,rbert Mön-djen
>
>-------" Umkodieren nach base64 "
>norbert@nolin:~> recode ../b64 < text.txt > text.b64
>
>-------" So sieht es dann aus "
>norbert@nolin:~> cat text.b64
>Ti5vLHJiZXJ0IE3Dtm4tZGplbgo=
Du hast Recht. Base64 wäre eine Kodierungsmöglichkeit. Leider ist
»recode« ebensowenig allgemein verfügbar wie die GNU-Fassungen von »find«
und »xargs«.
Ich sehe gerade: »uuencode« und »uudecode« sind immerhin im »Single Unix
Specification« als »User Portability Utilities« vorhanden.
Allerdings brauchen sie für diesen Zweck noch Nach- bzw. Vorbehandlung:
encode()
{
uuencode -m -- _ | sed -e '1d;/^====$/d' | tr -d '\n'
}
»tr« ist nötig, damit auch lange Eingaben nicht zu mehreren Zeilen
Ausgabe führen (auch bei »recode«).
decode()
{
{
printf '%s\n' 'begin-base64 000 _' < /dev/null &&
cat -- &&
printf '\n====\n' < /dev/null
} | uudecode -o /dev/stdout
}
>ich würde also vorschlagen die Dateinamen durch recode ../b64 zu pipen
>und dann abzulegen.
>Dann für rm durch recode /b64.. "zurückpipen".
>
>Allerdings wird das wohl mit Bordmitteln von find nicht direkt was
>werden. Wird dann wohl eher was in Form von find -exec script \{\} \;
Oft ist es lästig, erst eine Skript-Datei »script« zu erstellen (wohin
nur mit ihr?). Dann bietet sich statt dessen
$ find ... -exec sh -c \
'eine Kommandozeile, die die positional parameters nutzt' sh '{}' \;
an (Beispiel siehe unten).
>Oder auch sowas (eine Zeile):
>find . | (while read f ; do echo -n "`date +%s` , " ; echo "$f" | recode ../b64 ; done )
Damit das funktioniert, müsste man allerdings jeden Dateinamen einzeln
durch »recode« schieben. Eine Verkettung der Dateinamen -- wie hier --
mit newlines hat bereits verloren: Newlines in Dateinamen können damit
nicht von die Dateinamen trennenden Newlines unterschieden werden. Das
einzige sichere Trennzeichen für unkodierte Dateinamen ist ASCII NUL.
Alles andere kann in Dateinamen vorkommen.
Man könnte jedoch so vorgehen:
$ find DIR COND -printf '%T@:' \
-exec sh -c \
'printf %s "$1" | recode ../b64 | tr -d \\n && printf \\n' \
sh '{}' \;
Damit erhält man viele Zeilen, mit Newlines getrennt. In jeder Zeile
befindet sich zuerst das Dateidatum in Sekunden seit 1970-01-01T00:00:00
GMT (unkodiert), danach hinter einem »:« der Dateiname, Base64-kodiert,
jedoch ohne Zeilenumbruch auch bei langen Dateinamen.