skip123
Goto Top

Script zum Löschen von bestimmten Dateien

Hallo zusammen ! face-smile

es geht um folgenden sachverhalt: wir haben hier ein linux system auf dem bestimmte dateien verschoben werden sollen.... diese dateien liegen mir anhand einer liste vor.
(pro zeile ein dateiname)

da das verzeichnis gefühlte 1000 unterordner hat (also rekursiv müsste die suche auf jedenfall sein) und das ca. 700 dateien sind, die verschoben werden müssten kann sich ja sicherlich jeder
vorstellen wie lange das dauern würde.

meine frage ist deshalb ob es irgendein script oder befehl gibt, das diese dateinamen aus der mir vorliegenden datei zeile für zeile überprüft, sucht und dann an einen
bestimmten platz verschiebt ?

mit linux ist doch so gut wie alles möglich face-smile

mit freundlichen grüßen
skip123

Content-Key: 97012

Url: https://administrator.de/contentid/97012

Printed on: April 19, 2024 at 03:04 o'clock

Member: theton
theton Sep 16, 2008 at 07:21:32 (UTC)
Goto Top
Das ist mit jeder beliebigen Skript-Sprache möglich. In Perl z.B.

#!/usr/bin/perl

my $filename = "thisfile.txt"; # unsere datei mit der liste  
# datei zum lesen oeffnen
open(HANDLE, "< $filename") or die "Couldn't open file '$filename' for reading!\n";  
# datei zeilenweise einlesen
while($line = <HANDLE>) {
    # tu etwas mit dieser Zeile, z.B. die Datei verschieben
    chomp($line); # zeilenumbruch entfernen
    $out = `mv $line /mein/neuer/platz`;
    # ggf Output ausgeben
    if($out) {
        print $out."\n";  
    }
}
# datei schliessen
close(HANDLE);
Member: skip123
skip123 Sep 16, 2008 at 07:51:43 (UTC)
Goto Top
das ging ja schnell face-smile hätte garnicht mit so einer zügigen antowort gerechnet....

vielen dank schon mal

aber kann es sein das das script nur funktioniert wenn sich alle dateien in einem ordner befinden ? das ist bei uns aber nicht der fall.
sind zwar im prinzip in einem ordner aber der ist nochmal in tausende unterordner unterteilt, worin sich letztendlich dann die gesuchten dateien befinden...

gibt es da noch ne möglichkeit das ganze vielleicht rekursiv zu machen..
Member: theton
theton Sep 16, 2008 at 07:56:07 (UTC)
Goto Top
Nimm einfach anstatt dem mv-Befehl einen find-Befehl der die Dateien sucht und dann mittels des Parameters '-exec' verschiebt. Siehe dazu 'man find'.
Member: skip123
skip123 Sep 16, 2008 at 08:35:19 (UTC)
Goto Top
sorry aber ich komm immernoch nicht so richtig weiter face-sad

versuche die ganze zeit find und exec einzubauen aber immer kommt ne fehlermeldung

#!/usr/bin/perl
my $filename = "test.txt"; # unsere datei mit der liste  
# datei zum lesen oeffnen
open(HANDLE, "< $filename") or die "Couldn't open file '$filename' for reading!\n";  
# datei zeilenweise einlesen
while($line = <HANDLE>) {
    # tu etwas mit dieser Zeile, z.B. die Datei verschieben
    chomp($line); # zeilenumbruch entfernen
    $out = `find $line -exec mv /root/hiersolltenjetztdateiensein`;
    # ggf Output ausgeben
    if($out) {
        print $out."\n";  
    }
}
# datei schliessen
close(HANDLE);

die fehlermeldung lautet:
find: missing argument to `-exec'  
Member: theton
theton Sep 16, 2008 at 08:45:08 (UTC)
Goto Top
find /oberordner/der/dateien/ -name $line -exec mv {} /zielordner

So sollte der Befehl funktionieren. Keine Garantie. Beispiele finden sich aber bestimmt auch im Netz.
Member: skip123
skip123 Sep 16, 2008 at 11:22:28 (UTC)
Goto Top
sorry das ich hier so nerven muss aber ich bekomm es einfach nicht hin:

hab nun immerhin schon rausgefunden das der befehl wie folgt funktioniert wenn ich ihn anhand von ein paar testdateien und ordnern teste:

find /test -name "test1" -exec mv {} /tempo \;  
oder so
find /test -name "test1" -exec bash -c "mv {} /tempo" \;  

wie gesagt, so funktioniert der befehl, wenn ich diesen befehl allerdings in das script oben einbaue funktioniert er nicht ? wie kann das sein ?

script sieht zur zeit so aus:
#!/usr/bin/perl

my $filename = "test.txt"; # unsere datei mit der liste  
# datei zum lesen oeffnen
open(HANDLE, "< $filename") or die "Couldn't open file '$filename' for reading!\n";  
# datei zeilenweise einlesen
while($line = <HANDLE>)
{
    # tu etwas mit dieser Zeile, z.B. die Datei verschieben
    find /test -name $line -exec bash -c "mv {} /tempo" \;  

}
# datei schliessen
close(HANDLE);

fehlermeldung:
Backslash found where operator expected at ./delete line 10, near ""mv {} /tempo" \"  
        (Missing operator before  \?)
syntax error at ./delete line 10, near ""mv {} /tempo" \"  
Execution of ./delete aborted due to compilation errors.

wäre echt super wenn einer ne lösung weiß.... bin fast am verzweifeln face-sad

mfg skip123
Member: theton
theton Sep 16, 2008 at 11:46:43 (UTC)
Goto Top
Du musst den Befehl schon als Perl-Code einbinden. D.h. dass z.B. Anführungsstriche escaped werden müssen und dass der gesamte Befehl beim Ausführen in Backticks eingeschlossen werden muss. Beispiel:

$command = "befehl --mit \"parametern\""; $out = `$command`;  

Im Skript könnte das also z.B. so aussehen:

#!/usr/bin/perl
my $filename = "test.txt"; # unsere datei mit der liste  
# datei zum lesen oeffnen
open(HANDLE, "< $filename") or die "Couldn't open file '$filename' for reading!\n";  
# datei zeilenweise einlesen
while($line = <HANDLE>) {
    # tu etwas mit dieser Zeile, z.B. die Datei verschieben
    chomp($line); # zeilenumbruch entfernen
    $command = "find /test -name \"$line\" -exec mv {} /tempo";  
    $out = `$command`;
    # ggf Output ausgeben
    if($out) {
        print $out."\n";  
    }
}
# datei schliessen
close(HANDLE);
Member: skip123
skip123 Sep 16, 2008 at 13:39:03 (UTC)
Goto Top
ok... lange störe ich nicht mehr... bin nämlich kurz vorm aufgeben:

script sieht zur zeit wie folgt aus:

#!/usr/bin/perl

my $filename = "test.txt"; # unsere datei mit der liste  
# datei zum lesen oeffnen
open(HANDLE, "< $filename") or die "Couldn't open file '$filename' for reading!\n";  
# datei zeilenweise einlesen
while($line = <HANDLE>)
{
        # tu etwas mit dieser Zeile, z.B. die Datei verschieben
        chomp($line); # zeilenumbruch entfernen
        $command = "find /test -name \"$line\" -exec mv {} /tempo";  
        $out = `$command`;
        # ggf Output ausgeben
        if($out)
        {
                print $out."\n";  
        }
}
# datei schliessen
close(HANDLE);

fehlermeldung:
find: missing argument to `-exec'  

das ist die gleiche fehlermeldung die ich erhalte, wenn ich den befehl einzeln wie folgt ausführen würde:
find /test -name "test1" -exec mv {} /tempo;  

Grund: "\" fehlt, Befehl muss also wie folgt aussehen:
find /test -name "test1" -exec mv {} /tempo \;  

wenn ich diesen backslash jetzt oben einbauen will, "denkt" der rechner sicherlich das ich ein ausführungszeichen escapen will, da die zeile ja wie folgt enden würde:
$command = "find /test -name \"$line\" -exec mv {} /tempo \";   

führe ich das script mit der abgeänderten zeile aus, kommen gleich noch mehr fehlermeldungen:
Backslash found where operator expected at ./delete line 16, near "print $out."\"  
  (Might be a runaway multi-line "" string starting on line 11)  
        (Do you need to predeclare print?)
String found where operator expected at ./delete line 19, near "# find /test -name $line -exec bash -c ""  
  (Might be a runaway multi-line "" string starting on line 16)  
        (Missing semicolon on previous line?)
Bareword found where operator expected at ./delete line 19, near "# find /test -name $line -exec bash -c "mv"  
        (Missing operator before mv?)
syntax error at ./delete line 16, near "print $out."\"  
Search pattern not terminated at ./delete line 19.

So. und meine allerletzte frage: wenn ich mir den find befehl so angucke müsste dann nicht die variable ($line) OHNE anführungszeichen sein, also:
$command = "find /test -name $line -exec mv {} /tempo \";   
da er ja sonst nach dem wort "$line" sucht und nicht nach dem inhalt der variablen ?

sorry für den ganzen stress
mfg
skip123
Member: theton
theton Sep 16, 2008 at 14:08:28 (UTC)
Goto Top
Auch Backslashes kann man als Escape-Sequenz einfügen. Will man also ein einzelnes Backslash im String haben, schreibt man einfach '\\'. Ob der Dateiname in Anführungsstrichen steht, dürfte find eigentlich egal sein. Da du sie in deinem find-Befehl drin hast, hab ich sie auch einfach mal mit reingenommen. Der Befehl

find /test -name "test1" -exec mv {} /tempo \;  


Muss als Perl-String also so aussehen:

"find /test -name \"test1\" -exec mv {} /tempo \\;"  

Im Übrigen sind Nachfragen kein Problem. Dafür sind wir ja hier. Also nicht gleich aufgeben. face-smile
Member: skip123
skip123 Sep 17, 2008 at 06:45:15 (UTC)
Goto Top
So. Endlich funktionierts !

Nochmal ein ganz großes Dankeschön an theton ! Ohne dich hätte ich das echt nie geschafft !

Aber in Zukunft weiß ich ja, wo ich meine Fragen stellen kann.

EDIT:

sorry aber ich muss das thema doch nochmal aufgreifen face-sad die anforderungen an das script sind jetzt noch kurzfristig gewachsen face-sad

erstmal die problembeschreibung: der ordner der durchsucht wird enthält (wie schon erwähnt) sehr viele unterordner, welche ebenfalls wieder unterordner enthalten. die dateien die von dem script gesucht werden kommen in mehreren dieser unterordner vor.

das script verschiebt zurzeit ja alle dateien in einen von mir definierten ordner und überschreibt dann natürlich die dateien, die sie aus einem zuvor schon gefundenen unterordner verschoben hat. ergebnis: im durchsuchten ordner gab es die datei "xyzabc" merhmals (da in verschiedenen unterordnern vorhanden) aber in dem verzeichnis wo alle dateien hingeschoben werden ist die datei "xyzabc" jetzt nur noch einmal vorhanden, da sie mehrmals überschrieben wurde.

meine vorstellung wäre jetz: jedesmal wenn per find eine gesuchte datei gefunden wird, "merkt" sich das script den aktuellen ordner durch das speichern der ausgabe von pwd und verschiebt dann die datei in ordner "xyz" mit dem unterordner namens "pwdausgabe" (so das jede datei ihren unterordner den sie davor schon hatte im neuen verzeichnis auch hat)

*puh* ich hoffe das wäre irgendwie machbar.. hab da leider absolut keine idee :/

EDIT2:

Habs doch noch selber hinbekommen. ist jetzt zwar etwas umständlicher gelöst, aber naja face-smile
sind jetz 2 scripte statt einem, aber egal.

für alle interessierten poste ich mal noch die 2 scripte:

also das 1. script sieht wie folgt aus:
#!/usr/bin/perl
my $filename = "test.txt"; # unsere datei mit der liste  
# datei zum lesen oeffnen
open(HANDLE, "< $filename") or die "Couldn't open file '$filename' for reading!\n";  
# datei zeilenweise einlesen
while($line = <HANDLE>) {
        # tu etwas mit dieser Zeile, z.B. die Datei verschieben
        chomp($line); # zeilenumbruch entfernen
        $command = "find /test -name $line >> found.txt;";  
        $out = `$command`;
        # ggf Output ausgeben
        if($out)
        {
                print $out."\n";  
        }
}
# datei schliessen
close(HANDLE);

und das 2. script:
#!/usr/bin/perl
my $filename = "found.txt"; # unsere datei mit der liste  
# datei zum lesen oeffnen
open(HANDLE, "< $filename") or die "Couldn't open file '$filename' for reading!\n";  
# datei zeilenweise einlesen
while($line = <HANDLE>) {
        # tu etwas mit dieser Zeile, z.B. die Datei verschieben
        chomp($line); # zeilenumbruch entfernen
        $command = "cp $line /tempo$line";  
        $out = `$command`;
        # ggf Output ausgeben
        if($out)
        {
                print $out."\n";  
        }
}
# datei schliessen
close(HANDLE);

Nochmal einen wirklich FETTEN dank an theton.... ohne sein script als vorlage hätte ich das nicht geschafft ! face-smile

mfg skip123