als RSS-Feed abonnieren
Hundezuechter
McKinsey
XML-Ferientermine
xml-ferientermine
Go-Spiel-bei-DGS
Projektarbeit
Wohnungssuche
Bewerbungen
Ruby-in-Second-Life
Clatronic-CTV731-bei-Saturn
T_Shirts_Mousepads
Singleboersenvergleich
TimeSystem
Katzen
katzen
Arbeitsamt_I
Klick
2007-01-21
2007-01-19
Leapc
iMacros-to-Watir-Konverter
ASP
Ruby-Stocks
National-Geograpic
Google-Kalender
XML-Ruby
XMLTV
css
scribus
ruby-links
c-sharp
videos-fuer-psp-konvertieren
tchibo-infoglobe
uuencode-ruby
linux-phone-neo-1973
mx600-mouse
ruby-mechanize-https
ncurses
internetcafes
corba
ruby-einladung
ruby-setup
ruby-xml
watir
find-ersatz-in-ruby
ruby-priority-queue
gem-needle
gem-dependency
index
DotNetTests
TDD
Gadgets
RSS
Geocaching
2006-10-22_CSS_hier
2006-10-22-zaurus
2006-10-22
2006-10-22_Mono_und_Linux


vom: 2006-10-25 22:19

Ein komfortabler find-Ersatz mit Ruby

Unter Unix gibt es den find-Befehl, mit dem man im Dateisystem nach Dateien suchen kann, die bestimmte Kriterien erfüllen – der einfachste Fall dürfte die Suche nach einem bestimmten Dateinamen oder einer Gruppe von Dateien mit ähnlichem Namen sein.

Der Aufruf von find $HOME -name "*.sql" -print sucht beispielsweise nach allen Dateien, deren Name mit ’.sql’ aufhört, und die sich unterhalb des eigenen HOME-Directories befinden.

Wie kann man so etwas nun mit Ruby realisien?

Fangen wir mit einem einfachen Beispiel an:


    require 'find'

    path="/home/tp" 

    Find.find(path) {|f|
      puts f
    }

Hiermit werden sämtliche Files unterhalb des Directories /home/tp aufgelistet:

/home/tp
/home/tp/shakes.txt
/home/tp/.aufheben.rhtml.swp
/home/tp/LuLaLiebe_Architekture.sxw
/home/tp/shyla144_166.jpg
/home/tp/w2dlogo.jpg
/home/tp/shyla88cols2.jpg
/home/tp/shyla134_166.jpg
/home/tp/shylacols2.jpg
/home/tp/html-groessen-header.sxc
...

Den Suchpfad fest im Programm eingebaut zu haben, ist natürlich unpraktisch, weshalb wir einen (oder mehrere) Suchpfad(e) beim Aufruf des Programms auf der Kommandozeile übergeben.

Wir modifizieren deshalb unser Programm folgendermaßen:


    require 'find'

    path = ARGV

    path.each {|p|
      Find.find(p) {|f|
        puts f
      }
    }


Wir haben jetzt eine Schleife, die alle übergebenen Pfade nacheinander durchläuft.

Jetzt können wir beim Aufruf Pfade übergeben:

ruby find-test2.rb /home/bettina /home/tp liefert nun Informationen über alle angegebenen Pfade:
/home/bettina/
/home/tp
/home/tp/shakes.txt
/home/tp/.aufheben.rhtml.swp
/home/tp/LuLaLiebe_Architekture.sxw
/home/tp/shyla144_166.jpg
/home/tp/w2dlogo.jpg
/home/tp/shyla88cols2.jpg
/home/tp/shyla134_166.jpg
/home/tp/shylacols2.jpg
/home/tp/html-groessen-header.sxc

Anmerkung: Weil im ersten Pfad keine Dateien vorhanden sind, wird nur diese eine Zeile ausgegeben, falls dort Dateien existieren würden, würden diese ebenfalls ausgegeben werden.

Jetzt wollen wir natürlich nicht sämtliche Dateien auflisten, sondern gezielt nach bestimmten Dateien suchen können.

Praktisch und anschaulich wäre vielleicht ein Aufruf in der Form

such.rb "*.sql" in /home/bettina /home/tp

Man sieht, als erstes Argument wird das Suchmuster übergeben, dann kommt ‘in’ und dann die Pfade, in denen gesucht werden soll.

Wie muß unser Programm nun aussehen, damit dieses Verhalten ausgeführt wird?


    require 'find'

    path = ARGV
    suchmuster = path.shift

    path.each {|p|
      Find.find(p) {|f|
        puts f if File.fnmatch(suchmuster, f)
      }
    }

Was haben wir gemacht? Das Suchmuster ist das erste übergebene Argument. Dieses wird aus dem Array der übergebenen Argument mit ‘shift’ entfernt. Übrig bleiben nun nur noch die Pfade, in denen gesucht werden soll. Diese werden wieder in einer Schleife nacheinander durchlaufen.

Weiterhin haben wir ‘File.fnmatch(...’ verwendet. Diese Methode gibt ‘true’ zurück, wenn der Dateiname mit dem gewünschten Suchmuster übereinstimmt. Bei dieser Methode werden nicht die üblichen Regular-Expressions verwendet, sondern das Matching von Dateien nach Suchmustern, die bei der Unix-Shell verwendet werden (”*.c” und ein Dateiname “project.c” würde also ‘true’ liefern).

Wir geben jetzt die Dateinamen jetzt nur noch mit ‘puts’ aus, wenn eine Übereinstimmung mit dem Suchmuster vorhanden ist.

Beipspiel:

ruby such.rb "*.jpg" in /home/bettina/ /home/tp

liefert uns

/home/tp/shyla144_166.jpg
/home/tp/w2dlogo.jpg
/home/tp/shyla88cols2.jpg
/home/tp/shyla134_166.jpg
/home/tp/shylacols2.jpg
/home/tp/shyla212_166.jpg
/home/tp/Imaging-1.1.5/Images/lena.jpg
/home/tp/sabrina_klein.jpg
/home/tp/Thomas_NV.jpg
/home/tp/xmltv-0.5.42/choose/tv_check/tv_check_doc.jpg
/home/tp/sit-in-the-corner-dumbass.jpg
/home/tp/Susanne_39_1044108_fuer_PSP.jpg
/home/tp/Susanne_39_1044108.jpg
/home/tp/geh-sterben.jpg
/home/tp/ruby-test/imageinfo/Susanne_39_1044108_fuer_PSP.jpg
/home/tp/ruby-test/imageinfo/sabrina_klein.jpg
/home/tp/ruby-test/thomas_blog/blog/res/images/header.jpg
...

also genau das, was wir haben wollten.

Kontakt: Thomas Preymesser
Prinzenallee 36
13359 Berlin
Telefon: 030 - 49 78 37 06
mobile: 0172-8111959
eMail: thopre@gmail.com