• Willkommen im Linux Club - dem deutschsprachigen Supportforum für GNU/Linux. Registriere dich kostenlos, um alle Inhalte zu sehen und Fragen zu stellen.

[gelöst] Dateipfadlänge prüfen

thapate

Newbie
Hallo zusammen!

Ich suche bzw. bin gerade dabei ein Script zu erstellen das einen bestimmten Pfad durchsucht (z.B. \home\ordner1\) und mir dabei alle Dateien rausfiltert bei denen die Dateipfadlänge z.B. größer 200 Zeichen ist. Alle Dateien die rausgefiltert wurden sollen in eine txt geschrieben werden. Die erstellte Textdatei soll dann per Mail an eine bestimmte Mailadresse geschickt werden. Dieses Script sollt täglich laufen (per Cronjob gesteuert).

Wäre super dankbar wenn mir jemand weitehelfen könnte :)

Viele Grüße
ThaPate
 
Hm, was hast Du denn schon angedacht? Ein komplettes skript wird Dir hier keiner schreiben, wir helfen bei spezifischen Problemen.

Übrigens: / != \
 
OP
T

thapate

Newbie
Erstmal Danke für den Tipp ;-)

Meine ersten versuche am Script:

#!/bin/bash

find - "dateipfad laenger 200" < laenge200txt.

mail -s "subject" adresse@ziel.test < laenge200.txt
echo "das hier wird der body" | mail -s "subject" adresse@ziel.test

#ENDE

Ich weis leider nicht mit welchem Befehl ich mir Dateien anzeigen lassen kann deren Dateipfad 200 Zeichen überschreitet.
Hab auch schon gegoogelt, aber nichts gefunden. Wahrscheinlich gibt es andere Möglichkeiten den Dateipfad zu filtern, aber ich habe als erstes an find oder locate gedacht...

Ich hoffe Ihr könnt mir einen Tipp geben!

Viele Grüße
ThaPate
 

abgdf

Guru
Hi,

bei bash gibt's leider oft Probleme bei Listen von Dateinamen, wenn diese Leerzeichen enthalten.

Daher mal in Perl:
Code:
#!/usr/bin/perl

use warnings;
use strict;

use File::Find;

my $directory = "/home/user/";
my $fnlength = 200;

my $outfile = "laenge$fnlength.txt";

open(FH, ">$outfile") or die "Error opening '$outfile': ?!";

find(\&wanted, $directory);

sub wanted {
    my $filename = $File::Find::name;
    if(length($filename) > $fnlength) {
        print(FH "$filename\n");
    }
}

close(FH);
Gruß
 
A

Anonymous

Gast
abgdf schrieb:
Daher mal in Perl:
Dein Script scheint irgend welche Problem zu bekommen wenn er nicht genügend Rechte auf ein Verzeichnis hat,
./test.pl
Can't cd to (/home/rob/buch/ldd3_pdf/) test: Keine Berechtigung
at ./test.pl line 15
und außerdem ist mir dein Script wiedermal viel zu lang und zu langsam ;) und ich geb mal meinen Senf in awk dazu
Code:
find | awk 'length > 200'
wenn der Dateiname nicht mitgezählt werden soll (wird leider nicht ganz klar mit der Aussage Pathlänge ob jetzt mit oder Dateinamen ), wirds etwas länger bleibt aber immer noch unter einer viertel Zeile, oder man sucht mit find nur die Verzeichnisse.
Das ganze dann in eine Mail zu schreiben
Code:
find | awk 'length > 200' | mail -s "zu lange Dateienamen" user@rechner.irgendwo

robi
 

abgdf

Guru
Und damit kommst Du auch in Verzeichnisse, in denen Du die Rechte nicht hast?
und außerdem ist mir dein Script wiedermal viel zu lang und zu langsam
Man kann natürlich auch schreiben:
Code:
perl -e '@a=`find "/home/user/"`;for(@a){if(length($_)>200){print}}'
Ich find's aber ungeil, weil ich Perl als Programmiersprache sehe, in der man möglichst Module statt "system()"-Calls verwenden und sich zudem verständlich ausdrücken sollte.
Macht doch nichts, wenn ein Skript dadurch mal ein bißchen länger wird. Oder spielen wir hier Golf ?
Immerhin: TMTOWTDI.

Gruß
 
OP
T

thapate

Newbie
Erstmal vielen Dank für die schnelle Hilfe!

Code:
 find | awk 'length > 200' | mail -s "zu lange Dateienamen" user@rechner.irgendwo
Habe es hiermit getestet! Klappt soweit wunderbar!
Werde noch kleine Änderungen vornehmen (das Ergebnis in eine Textdatei etc.)

wenn der Dateiname nicht mitgezählt werden soll (wird leider nicht ganz klar mit der Aussage Pathlänge ob jetzt mit oder Dateinamen ), wirds etwas länger bleibt aber immer noch unter einer viertel Zeile, oder man sucht mit find nur die Verzeichnisse.
Der Dateinamen soll mitgezählt werden! => Wie es das obere Script auch macht :)

Noch eine Frage...
Gibt es die Möglichkeit ein bestimmtes Verzeichnis auszuschließen?

Viele Grüße
ThaPate
 

abgdf

Guru
Gibt es die Möglichkeit ein bestimmtes Verzeichnis auszuschließen?
Im Perl-Skript oben
Code:
if($filename =~ m/^Verzeichnis/) {return;}
in die foreach-Schleife in der Funkion wanted() einfügen. Die Slashes in "Verzeichnis" dabei als "\/" (Backslash und Slash) schreiben.

Hier dürfte vielleicht irgendwo der Punkt sein, an dem awk nicht mehr feinmaschig genug ist (vielleicht hat find aber doch noch eine entsprechende Option) (und obwohl ich durchaus bewundere, was robi alles mit awk anstellt :wink:).

Gruß
 
A

Anonymous

Gast
abgdf schrieb:
Hier dürfte vielleicht irgendwo der Punkt sein, an dem awk nicht mehr feinmaschig genug ist

;) ;) ;) awk nicht feinmaschig genug. ;) ;) ;) das währe ja wie Reguläre Ausdrücke nicht universell einsetzbar. Aber ich habe auf den Tipp " ! -path VERZEICHNIS " als find-Option erlinkt, das ist kürzer und leichter zu verstehen und zu durchschauen.

robi
 
OP
T

thapate

Newbie
Script funktioniert soweit wunderbar....
Hab aber noch ein Problem mit der Ausgabe bzw. die Ausgabe als txt-Datei per Mail zu versenden.

Code:
find | awk 'length > 200' >test.txt | mail -s "zu lange Dateienamen" -a test.txt user@rechner.irgendwo
Bekomme dann eine Mail mit angehangener txt-Datei, aber der Inhalt der txt-Datei ist leer!
In der "test.txt" auf dem Server sind aber alle Dateipfade aufgelistet, die größer 200 Zeichen sind.

Ich glaube das ich mit dem Anhang was falsch mache bzw. einen falschen Befehl dafür verwende!
Danke im Voraus!

Viele Grüße
ThaPate
 
A

Anonymous

Gast
Kleiner Denkfehler ;) , du startest dein mail zu früh, da ist die Datei noch gar nicht beschrieben.
Versuch mal folgendes
Code:
find | awk 'length > 200'  > test.txt && echo "siehe Datei anbei" | mail -s "zu lange Dateienamen" -a test.txt user@rechner.irgendwo

robi
 
Ungetestet würde ich mit der Shell mal sagen:
Code:
find `pwd` -type f  | while read file
do
if [ "${file:0:200}" != "${file}" ]
then
  echo OOps, ${file} ist zu lang.
fi
done

Hmm oder müsste es ${file:0:199} oder ${file:0:201} heissen ? ;-)

Haveaniceday
 
OP
T

thapate

Newbie
Vielen Dank!!!
Hat nun soweit alles prima geklappt!

Würde gerne das Script noch ein wenig verfeinern :)

Wenn ich dem Scipt den Pfad mitgebe
Code:
find /public/xy/*
zählt er mir den Teil "/public/xy/" auch schon mit...
Das könnte ich auch so umgehen, dass ich einfach anstatt 200 => nach 210 Zeichen suchen lasse.

Aber da habe ich nun folgendes Problem:
Dateisstruktur sieht ungefähr so aus:

\public\xy\abcdefg
\public\xy\123456789
\public\xy\abc
\public\xy\asdf123456789
\public\xy\xy
\public\xy\1111111000000000000

Ich hätte auch gerne das der Teil \public\xy\abcdefg etc. nicht mitgezählt wird!
Wie ihr sehen könnt sind die jeweiligen Ordner unterschiedlich lang (Dateinamen).
Also wär es ideal wenn die Dateipfade ab \public\xy\abcdefg\* mitgezählt werden würden!
Müsste ich nun für jeden Ordner ein eigenes Script erstellen?
Und ist es möglich das keine Mail versendet wird, wenn es keine Dateipfade größer z.B. 210 gibt?

Danke für eure Mühe!!!!
Viele Grüße
ThaPate
 
A

Anonymous

Gast
thapate schrieb:
Ich hätte auch gerne das der Teil \public\xy\abcdefg etc. nicht mitgezählt wird!
Als erstes mal im Filesystem genau umsehen wie die Datein und ihre Pfade denn in Linux genau aussehen. Es macht hier einen Riesenunterschied ob "\" oder "/" weil das eine ein etwas problematisches Sonderzeichen ist, das fast überall Sonderbehandlung benötigt.

Wenn du die Teilbereiche des Pfades nicht mitzählen willst, aber dennoch mit ausgegeben werden sollen.

Code:
find  | awk -F "/" '(length - length($1) - length($2) - length($3) -2) >200'
Dann werden vor dem Vergleich jeweils die Länge der ersten 3 Verzeichnisse und 2 Mal das Trennzeichen "/" von der Gesamtlänge abgezogen, aber alles ausgegeben.

Wenn du nur eine Mail schicken willst, wenn es solche Datein gibt, ganz einfach. Erst die Datei entsprechend anlegen. Dann im nächsten Schritt testen ob diese Datei leer ist. Ist sie nicht leer dann Mail schreiben sonst eben nicht.

Manpage von test und bash insbesondere Begriffe wie if - then - else - fi werden dich weiterbringen.

robi
 
OP
T

thapate

Newbie
Vielen Dank rodi!

Meine Pfadangaben hab ich aus versehen falsch angegeben...
Es sollte eigentlich /public/xy/123 etc. heißen!

Werde mich gleich mal ran machen...

Viele Grüße
ThaPate
 
OP
T

thapate

Newbie
Mein Script sieht momentan so aus

Code:
find /public/xy/123 | awk -F "/" '(length - length($1) - length($2) - length($3) -3) >200' > test.txt && echo "zu lange Dateienamen"  | mail -s "zu lange Dateienamen" -a test.txt mail@blabla.de

Nun bekomme ich aber weiterhin Dateien ausgegeben die einen Dateipfad weniger 200 haben (wenn ich die zeichen für /public/xy/123 abziehe)

Habe ich da was falsch umgesetzt?
 
A

Anonymous

Gast
In diesem Fall probier mal noch "- length($4) " dazuzunehmen,
Erklärung:
Code:
Feldbegrenzer=F="/"
      / public   /   x y   /    123   / ----------------#
$1      $2          $3          $4

robi
 
OP
T

thapate

Newbie
So da bin ich wieder ;-)

Code:
 find /public/xy/* | awk -F "/" '(length - length($1) - length($2) - length($3) - length($4) -4) >200' > test.txt && echo "zu lange Dateienamen"
if test -s test.txt
then
mail -s "zu lange Dateienamen" -a test.txt mail@blabla.de
fi
Wenn ich dieses Script ausführe bekomme ich kein Ergebnis...

die "if-Formel" kann ich ja nicht pipen oder?
Code:
 find /public/xy/* | awk -F "/" '(length - length($1) - length($2) - length($3) - length($4) -4) >200' > test.txt && echo "zu lange Dateienamen" |
if test -s test.txt
then
mail -s "zu lange Dateienamen" -a test.txt mail@blabla.de
fi

Weis gerade nicht weiter :-(

Viele grüße
ThaPate
 

abgdf

Guru
... ist ja auch kaum noch lesbar.

Das Perl-Skript oben dürfte übrigens schneller laufen, wenn man in der find-Anweisung noch "no_chdir" mitgibt; das müßte wahrscheinlich so aussehen:
Code:
find({wanted => \&wanted, no_chdir => 1 }, $directory);
Gruß
 
Oben