Re: Leerzeichen/Dateinamen in Shellscripts

From: Oliver Fromme <olli(at)secnetix.de>
Date: Fri, 2 Aug 2002 20:40:33 +0200 (CEST)

Philon <philon(at)macnews.de> wrote:
>
> > Das ist schonmal schlecht. Die Ausgabe von ls läßt sich
> > nicht verläßlich parsen, höchstens, wenn Du die Option -B
> > verwendest, aber das wird eher ziemlich aufwendig.
>
> mein ls hat keine -B Option.

Dann solltest Du dringend updaten. ls -B gibt es in Free-
BSD seit 2.2.7-Release, d.h. seit etwa vier Jahren, und
es ist die einzige Möglichkeit, mit ls alle Sonderzeichen
in Dateinamen auf eindeutige Weise zu ermitteln.

> > Du solltest bedenken, daß es nur zwei Zeichen gibt, die
> > unter UNIX ich Dateinamen nicht vorkommen können: der
> > Schrägstrich und Nullbytes. Alles andere ist erlaubt,
> > z.B. auch Newlines, Backspaces, Escapes etc. Da sind
> > Spaces und Tabs eher noch das geringere Übel.
>
> Die Dateien werden von Clients mit Windows und Mac OS erstellt. Da
> reduziert sich die Liste um ein gutes Stück. Und nach meinem letzten
> Test gab nichts weiter besonderes als das Leerzeichen vor. Grössere
> Dinge sollten also von vornherein garnicht auftreten.

Das kommt drauf an, ob es Dir darauf ankommt, »übliche«
Fälle abzudecken, oder ob Du auch damit rechnen mußt, daß
einer der Benutzer absichtlich versucht, »böse« Dinge an-
zustellen.

> > Du solltest Dir einen anderen Weg überlegen, die Datei
> > liste zu erstellen. Es gibt da eine ganze Reihe von Mög-
> > lichkeiten. Was sich am ehesten anbietet, hängt davon ab,
> > was Du überhaupt machen willst, bzw. woher die Dateinamen
> > überhaupt kommen, oder nach welchen Kriterien sie ermittelt
> > werden sollen.
>
> Ich mach ja bis jetzt nur Basics mit shellscripts, um das übliche hier
> und da zu automatisieren. Bisher hatte ich da mit ls in eine Datei zum
> wieder ausgreppen und nachbearbeiten mit awk und sed eigentlich weder
> die Möglichkeiten (Regular Expressions) ausgeschöpft noch die Grenzen
> erreicht. Ich kam nur über Leerzeichen nicht hinweg.
>
> Wie ließen sich denn sonst noch Dateiexistenzen/Ordnerinhalte für ein
> Skript herausfinden?

Vielleicht solltest Du einfach mal den entsprechenden Ab-
schnitt aus Deinem Skript hier zitieren (wenn's nicht zu
viel ist). Dann kann man konkrete Verbesserungsvorschläge
machen.

Neben ls kann man auch find verwenden. Wenn Du die Ausgabe
von ls (oder find) dateiweise (also zeilenweise) verarbei-
ten möchtest, kannst Du z.B. in einer Schleife read ver-
wenden:

ls | while read DATEI; do echo "---$DATEI---"; done

Damit kriegst Du auch Leerzeichen und sogar Tabs in den
Dateinamen unverändert in die Variable, ohne mit IFS spie-
len zu müssen.

Allerdings werden Spaces und Tabs ganz am Anfang und ganz
am Ende entfernt, und mit Newlines in den Namen kommt es
natürlich auch nicht klar. Da gilt mein Hinweis von oben,
ob Du mit böswilligen Benutzern rechnen mußt. Auf jeden
Fall sollte Dein Skript robust genug sein, daß es in sol-
chen Fällen nicht die Löffel schmeißt, sondern die »bösen«
Dateien einfach ausläßt.

> Wir haben Fileserver-Volume der Daten vom Raid runterkopiert auf ne
> andere Platte damit ein anderer Rechner von den Daten ein Backup machen
> kann, ohne das an den Daten geändert wird. Letzteres machte immer
> wieder Probleme. Nunja, mit rsync wärs eigentlich am besten, das hatte
> aber nicht geklappt, da bin ich auf ditto gekommen.
>
> Im Endeffekt ists so.
> - Schau ins Serververzeichnis nach Dateien
> - Kopiere alle aktuellen Arbeitsordner rüber auf die andere Platte
> - Lass die Dateien mit ~ oder Leerzeichen am Anfang des Dateinamens aus
> (weshalb ein cp des ganzen Ordners z.B. nicht geht)

Nichts einfacher als das. Klar geht das mit cp:

cp -p [!~\ ]* Zielverzeichnis

(Das »!« ist in Shell-Patterns die Negation, d.h. kopiere
alles, was _nicht_ mit »~« oder Space beginnt. Beachte,
daß das Space mit einem Backslash geschützt werden muß, da-
mit der Tokenizer da nicht zuschlägt. Die Option -p möch-
test Du bei cp verwenden, damit Owner und Permissions mit-
kopiert werden und korrekt im Backup landen.)

Hat natürlich den Nachteil, daß die Kommandozeile nach der
Expansion durch die Shell zu lang werden kann, wenn da sehr
viele Dateien sind. Wenn man damit rechnen muß, sollte man
besser find + xargs verwenden:

find . -maxdepth 1 -name '[!~ ]*' -print0 \
| xargs -J '{}' -0 cp -p '{}' Zielverzeichnis

Das »-maxdepth 1« sorgt dafür, daß das find nicht in Unter-
verzeichnisse reingeht, was Du ja offenbar nicht möchtest.

Hmm, bei genauerem Hindenken fällt mir jetzt auf, daß das
ganze eigentlich auch mit cpio geht (kommt allerdings
nicht mit Newlines in Dateinamen zurecht):

find . -maxdepth 1 -name '[!~ ]*' | cpio -dump Zielverzeichnis

Gruß
   Olli

-- 
Oliver Fromme, secnetix GmbH & Co KG, Oettingenstr. 2, 80538 München
Any opinions expressed in this message may be personal to the author
and may not necessarily reflect the opinions of secnetix in any way.
"All that we see or seem is just a dream within a dream" (E. A. Poe)
To Unsubscribe: send mail to majordomo(at)de.FreeBSD.org
with "unsubscribe de-bsd-questions" in the body of the message
Received on Fri 02 Aug 2002 - 20:40:36 CEST

search this site