3 Fragen zu find Befehl

  • Hallo


    Vorweg:

      Ja ich habe die Man - Page von find gelesen.
      Ja ich habe diese vielleicht nicht verstanden.


    Frage 1:
    Wenn ich mit "find" Dateien bzw. Directories finde, welche "Leerzeichen" enthalten, bekommen ich mit find eine Ausgabe, damit Sie von der Shell weiterverarbeitet werden kann.


    z.B.: Die Datei hat den Namen

    Code
    ich bin eine datei


    und was ich brauchen würde wäre

    Code
    ich\ bin\ eine\ datei


    Frage 2:
    Kann ich mit find mehrere Dateien, Verzeichnisse bzw. Regular Expressions auf einmal finden.
    z.B.: Alle Dateien welche mit gif und jpg enden


    Frage 3:
    Wie kann ich mit find beim Suchen ein bestimmtes Verzeichnis auslassen.
    In der Man Page steht ein Beispiel mit

    Code
    find . -path './src/emacs' -prune -o -print


    Leider liefert es nicht das gewünschte Ergebnis.


    Danke Silent

  • Frage 2:
    Kann ich mit find mehrere Dateien, Verzeichnisse bzw. Regular Expressions auf einmal finden.
    z.B.: Alle Dateien welche mit gif und jpg enden


    find / |grep *.gif


    so müsste das gehn

  • Frage 2:
    mit müßte ist hier nicht geholfen.
    Aber find unterstützt einen ganzen Haufen von logischen Operatoren (Auszug aus der man-page):



    In deinem Fall ist wohl sowas wie richtig:


    Code
    find /usr/src -name \*.c -or -name \*.h


    Wenn du z.B. im Verzeichnis /usr/src (und allen Unterverzeichnissen) alle Dateien mit der Endung *.c und *.h suchst.


    marvel

  • Zu Frage 1:
    Ich meine zwar irgendwie, im Kopf zu haben, daß man find sowas angewöhnen kann, aber die Lösung, die mir jetzt sofort einfällt, benutzt einfach sed und regular expressions:


    Wenn es dir nur um Leerzeichen geht:


    Code
    find [wasauchimmer] | sed s/' '/'\\ '/g


    Oder du kannst die ganze Zeile in single quotes setzen:


    Code
    find [wasauchimmer] | sed s/^/\'/ | sed s/$/\'/


    Letzteres geht sicher auch in einem sed-Aufruf, ich muß allerdings zu meiner Schande gestehen, daß ich es nicht hinbekommen habe... unter perl ist das einfacher, da braucht man nix zu quoten ;)


    Zu Frage 3:
    Hmm... also bei mir tut es das. Kannst du vielleicht mal ein Verzeichnis und deinen Aufruf vorgeben? Vielleicht ist irgendwo noch ein subtiler Fehler drin, oder ein Sonderfall, den ich beim Ausprobieren jetzt auch nicht hatte.

  • Zitat

    Original von silent
    Frage 1:


    Eine weitere Variante diese Problems ist relativ einfach:
    export IFS="
    "

    Ja, mit "RETURN" dazwischen.
    Danach funktioniert find wie gewünscht. Und um den alten Zustand wieder herzustellen, vorher ein OLD_IFS=$IFS und danach export IFS=$OLD_IFS



    Frage 2:
    find / -name "*.gif"
    find . -regex "^.*(\.gif|\.bmp)$"


    Frage 3:
    Du stellst ein weiteres find davor, und pipst das Ganze über grep mit regex
    Also so:
    find / -type d |grep -E {regex mit dirs}| xargs find ....
    so ähnlich.

    Glotze: yaVDR (ASRock Q1900M, 4GB RAM, DD Cine S2 V6.5, ZOTAC GT630 (Rev. 2)
    Server: HP ProLiant MicroServer G8, VMware ESXi 5.5 :P


  • Zu 1:
    Ein perfektes Quoten kann fast beliebig kompliziert werden. Wenn du es aber nur mit leerzeichen zu tun hast sollte das folgende reichen:


    find . -exec echo \'\{\}\' \;


    Zu 2:
    Verschiedene Dateitypen:
    find . -name "*.jpg" -o -name "*.gif"


    Verschiedene Startverzeichnisse:
    find /tmp /var/tmp -name "*.gif"


    Zu 3:
    find . -path './CVS' -prune -o -path '*huhu*' -prune -o -exec echo \{\} \;


    sollte funktionieren. Wenn nicht machst du etwas falsch. (ggf. EXAKTES Testbeispiel hier angeben, damit man den Fehler suchen kann)


    Ulrich

  • Zuerst möchte ich mich bedanken für die vielen Hilfestellungen


    Also mit dem Script könnt ihr euch eine "Testumgebung" erstellen, damit ihr nicht alles reinklopfen müßt.


    sollte dann so aussehen



    @marauder
    die Lösung sehe ich als "Workaround", funktioniert natürlich auch
    richtig wäre allerdings

    Code
    find / |grep -e *.gif -e *.jpg


    marvel
    Schande über mich, danke jetzt weiß ich endlich, was die da ganz unten in der Man-Page damit meinen :wand

    Code
    jupiter testsilent $ find . -name *.gif -o -name *.jpg
    ./test.gif
    ./test.jpg
    jupiter testsilent $


    flosch
    zwar auch ein Workaround aber geht

    Code
    jupiter testsilent $ find . -name eine* | sed s/' '/'\\ '/g
    ./eine\ datei\ mit\ space
    jupiter testsilent $


    die 2. lösung geht bei mir nicht ;)

    Code
    jupiter testsilent $ find . -name eine* | sed s/^/\'/ | sed s/$/\'/
    './eine datei mit space'
    jupiter testsilent $


    @hulk
    Sorry die Antwort zu Frage 2 gefällt mir eigentlich nicht, net böse sein
    Die Antwort zu Frage 3


    Da läßt er zwar das Directory2 aus jedoch nicht den Inhalt ==> das will ich eigentlich nicht


    knebb
    Die IFS Variable gibts bei mir nicht und sie ändert auch nichts

    Code
    jupiter testsilent $ export IFS
    jupiter testsilent $ find . -name eine*
    ./eine datei mit space
    jupiter testsilent $ export IFS="
    > "
    jupiter testsilent $ find . -name eine*
    ./eine datei mit space
    jupiter testsilent $


    zu Frage 2
    funktioniert bei mir auch nicht

    Code
    jupiter testsilent $ find . -regex "^.*(\.gif|\.jpg)$"
    jupiter testsilent $ ls
    directory1  directory3            test.gif  test.txt
    directory2  eine datei mit space  test.jpg
    jupiter testsilent $


    zu Frage 3
    da läßt er das directory2 nicht aus, zumindest bei mir


    ulho
    aw 1 geht nicht

    Code
    jupiter testsilent $ find . -name eine* -exec echo \'\{\}\' \;
    './eine datei mit space'
    jupiter testsilent $


    aw 2 funktioniert, siehe oben
    zu aw 3
    warum hier nur die 3. Variante geht kapier ich zwar nicht ganz, aber zumindest funktioniert's :gaga


    Wie schon man sich die Zeit mit find verteibern kann.


    Danke
    Silent

  • Zitat

    Original von silent
    die 2. lösung geht bei mir nicht ;)

    Code
    jupiter testsilent $ find . -name eine* | sed s/^/\'/ | sed s/$/\'/
    './eine datei mit space'
    jupiter testsilent $


    Naja, du hast jetzt eben einen Namen mit single quotes. So kannst du ihn wunderbar an andere Programme weiterpipen und hast auch eventuelle andere Probleme umschifft, zum Beispiel mit Klammern oder ähnlichem im Dateinamen. Ich hatte quasi bei der zweiten Lösung schon etwas allgemeiner und weiter gedacht ;) Wie ulho übrigens auch, aber meine Lösung ist (zumindest bei mir) deutlich schneller, ich vermute, weil bei seiner Lösung für jede gefundene Datei ein echo aufgerufen wird, während bei mir nur ein oder zwei sed-Prozesse laufen, die in einem Rutsch den gesamten input verarbeiten.

  • Wichtig ist das du statt
    find . -name *.gif
    immer
    find . -name "*.gif"
    schreibst (oder '*.gif')!


    Beispiel:
    ./a.gif
    ./subdir/b.gif


    aus find . -name *.gif im aktuellen Verzeichnis macht die Shell sofort find . -name a.gif noch bevor das find gestartet wird (unterschied zu DOS: hier wird das * erst von dem gestarteten Befehl ersetzt).


    find . -path './directory1' -prune
    ist äquivalent zu
    find . -path './directory1' -prune -print
    und sehr unterschiedlich zu
    find . -path './directory1' -prune -o -print


    -prune verhindert, dass ein Zweig weiter durchlaufen wird. Der Startpunkt des abzuschneidenden Zweiges ist aber immer noch in der Bearbeitung und wird defaultmäßig ausgegenben.


    Einfacheres Beispiel


    ./a.gif
    ./b.gif
    ./c.gif


    find . -type f -name "a*" -print --> a.gif
    find . -type f -name "a*" -o -print --> b.gif, c.gif (und das aktuelle Verzeichnis: .)


    D.h. das erste findet alles was dem Muster a* entspricht, das zweite alles was dem Muster a* NICHT entspricht.


    Ulrich
    ------
    noch ein Nachtrag zum quoten:


    ./a b
    ./a
    ./b
    ./a'b


    (' ist bestandteil des Dateinamens!)


    find . -name 'a*' -type f -print0|xargs -0 ls -l


    liefert trotzdem das korrekte Ergebnis ("a b", "a", "a'b")
    Details: siehe Manpages

  • Zitat

    Original von silent
    knebb
    Die IFS Variable gibts bei mir nicht und sie ändert auch nichts


    Mach mal ein set |grep -i IFS. Da sollte sie auftauchen. Und Du solltest es GENAU so machen, wie ich es geschrieben habe: Mit den Anführungszeichen (") und dem Return DAZWISCHEN.
    Und sie ändert an dem Ergebnis auch nichts, aber Du kannst mit dem Ergebnis dann weiterarbeiten:

    Code
    OLD_IFS=$IFS
    IFS="
    "
    cp `find . -name "eine*"` geht
    IFS=$OLD_IFS
    cp `find . -name "eine*"` geht
    cp: Kopieren mehrerer Dateien, aber der letzte Parameter »geht« ist kein Verzeichnis
    »cp --help« gibt weitere Informationen.

    Kann ich doch nicht auf mir sitzen lassen, daß das nicht gehen soll ...grummel...:motz1


    Zitat

    zu Frage 2
    funktioniert bei mir auch nicht

    Code
    jupiter testsilent $ find . -regex "^.*(\.gif|\.jpg)$"


    Grummel, grummel, mußt de entsprechend ausmarkieren:
    find . -regex "^.*\(\.gif\|\.jpg\)$"
    Muß man denn hier alles selber machen.... :gap


    Zitat

    zu Frage 3
    da läßt er das directory2 nicht aus, zumindest bei mir

    Code
    jupiter testsilent $ find . -type d |grep -E {dir*2}| xargs find

    Ok, das geht auch so nicht, war nur schnell 'ne Idee hingepinnt. xargs bringt die Argumente aus der Pipe immer HINTER den anderen Argumenten und das mag find überhaupt nicht. Also anders:
    E=`find . -type d |grep -v "directory2"|grep -v "^\.$"`; find $E -name "*.txt"
    Gebe zu, ein wenig umständlich, die anderen Lösungen -so sie denn funktionieren- sind eleganter.

    Glotze: yaVDR (ASRock Q1900M, 4GB RAM, DD Cine S2 V6.5, ZOTAC GT630 (Rev. 2)
    Server: HP ProLiant MicroServer G8, VMware ESXi 5.5 :P

Jetzt mitmachen!

Sie haben noch kein Benutzerkonto auf unserer Seite? Registrieren Sie sich kostenlos und nehmen Sie an unserer Community teil!