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

bash - pipe basteln, bestimmte Ordner verschieben

Hallo!

Bin gerade dabei mir eine kleine Pipe zu basteln, die mir bestimmte Ordner aus mehr als 1000 herausfiltert und in einen seperaten übergeordneten Ordner verschiebt.

Kleine Veranschaulichung: aus /abc/{A}+{B}+{C} wird
/a/{A}
/b/{B} und
/c/{C}

(das Skript soll jedoch nur Schritt a durchführen, die Kriterien zum Filtern, möchte ich jeweils manuell festlegen)

Das Kriterium nach dem gefiltert wird, ist ein bestimmter Tag in einer .txt Datei eines jeden Ordners.

Bis jetzt sieht das so aus:
Code:
grep -l -r -i --include=*.txt EDITION:trash ./* > test.txt

Ich hatt mir das so vorgestellt, dass ich die Textdatei dann mittels einer Schleife abarbeite; also:
Code:
for i in `cat test.txt`;do
mv ${i} ../a/${i}

Dafür müsste ich die Textdatei jedoch erst in das entsprechende Format bringen. Am Ende jeder Zeile befindet sich immer noch die Textdatei. Wie kann ich diesen Teil entfernen, sodass nur noch auf den Pfad des Ordners mit der Textdatei gezeigt wird?



Gruß

Daniel
 

abgdf

Guru
Ok. Für manche Datenverarbeitungsaufgaben ist die Shell zu grob, das heißt, man kann das zwar machen, aber es ist aufwendig.
Die meisten nehmen dann Perl, ich meistens Python ("pydoc os").

Gruß
 
OP
D

Daniel_SGE

Newbie
Hallo!

Mit Python bzw. Perl kenne ich mich überhaupt nicht aus, hätte aber schon Interesse einzusteigen... Könntest du eventuell mal kurz skizzieren, welche Funktionen, Befehle gerade Python zur Verfügung stellt um solche Anforderungen zu leichter und schneller zu "bewältigen"?

Gruß

Daniel
 

abgdf

Guru
Gern:

5. File-operations

This script demonstrates some often-used file-operations:
Code:
#!/usr/bin/env python

import os
import sys

# Get current working directory:
PATH = os.getcwd()

FILE = PATH + "/myfile.txt"

# Test, if file exists:
if os.access(FILE, os.F_OK):
    print "File already exists."
    sys.exit(1)

fh = file(FILE, "w")

fh.write("This is a line of text.\n")
fh.write("This is another line.\n")

fh.close()

fh = file(FILE, "r")

a = fh.readlines()

fh.close()

for i in a:
    print i.rstrip("\n")

os.remove(FILE)

print "The directory contains:"
b = os.listdir(PATH)
for i in b:
    print i
9. Starting other processes from inside a Python-script

You can start other processes like that:

Code:
#!/usr/bin/env python

import os

os.system("ls")

Damit (mit "os.system()") kannst Du dann "mv" aufrufen.

Mit "os.popen()" kann man ggf. auch den Output von Befehlen wie "grep" abgreifen und weiterverarbeiten:
Code:
#!/usr/bin/env python

import os

ph = os.popen("ls")
a = ph.readlines()
ph.close()

print a
HTH
 

Wizzzard

Member
Mit python braucht man kein os.popen oder os.system um solche Sachen wie 'mv' oder 'ls' durchzuführen. Um wegen solcher Trivialitäten nicht die Betriebssystemunabhängigkeit zu verlieren, sollte man darauf verzichten.

Für 'mv' nimm die Bibliothek 'shutil'. Da ist ein move drin.

Das mit dem Verzeichnislesen lässt sich auf verschiedene Art und Weise durchführen. Beispielsweise mit os.listdir(), os.walk() oder os.path.walk().
 

regexer

Advanced Hacker
Daniel_SGE schrieb:
Wie kann ich diesen Teil entfernen, sodass nur noch auf den Pfad des Ordners mit der Textdatei gezeigt wird?
Code:
man dirname

... sofern ich deine Aufgabenstellung richtig verstanden habe, müsste das eigentlich auch ziemlich gut mit bash-Mitteln gehen.
 

abgdf

Guru
Hi,

danke für "shutil", da hab ich wieder was gelernt !

"os.path.walk()" ist ja nicht gerade einfach für einen Anfänger zu verstehen, deswegen dachte ich an popen und "find", das er ja besser kennt.

Ich glaube inzwischen auch, daß der OP mit "find | grep" irgendwie besser zurechtkommen müßte. Die Aufgabenstellung ist ja auch nicht gerade klar beschrieben, sonst könnte man wohl schnell mal ein Skript posten.

Gruß
 

regexer

Advanced Hacker
abgdf schrieb:
Die Aufgabenstellung ist ja auch nicht gerade klar beschrieben, sonst könnte man wohl schnell mal ein Skript posten.
Ehrlich gesagt habe ich's auch nicht ganz verstanden. Eventuell wäre es gut, etwas mehr Infos hinzuzufügen.

Für mich klingt es jedenfalls so, dass es wohl eher logische denn technische Probleme gibt...
 
OP
D

Daniel_SGE

Newbie
Ja, also die Lösung ist mir im Prinzip erstmal egal, hauptsache sie funktioniert.

Ich hab mal ein Diagramm gebastelt, vll. kann mans dann besser verstehen.


Das mit dirname hab ich dann auch gefunden, ich scheiter später dann aber den Leerzeichen in den Ordnernamen...

aktuelles Skript wäre demzufolge:

Code:
#!/bin/bash
grep -l -r -i --include=*.txt EDITION:trash ./* > /home/daniel/test.txt 
US=$(cat  /home/daniel/test.txt)
echo "$US"
for i in $US;do
echo ${i}
US=$(dirname "$i")
echo $US
#echo mv $US ../trash/
done
exit


Das mit Python werde ich mir aber auch versuchen anzueignen. Lese mir zur Zeit ein größeres Tutorial durch;)
 

Anhänge

  • Diagramm1.jpeg
    Diagramm1.jpeg
    61,5 KB · Aufrufe: 544

regexer

Advanced Hacker
Daniel_SGE schrieb:
ich scheiter später dann aber den Leerzeichen in den Ordnernamen...
Ja, ist klar. Die Komination Zwischendatei+cat+for ist etwas unglücklich. Für Leerzeichen kann das nicht funktionieren...

Probier mal:
Code:
#!/bin/bash
IFS=""
grep -l -r -i --include=*.txt EDITION:trash ./* | while read i
do
  echo "${i}"
  # hier deine Logik
done
 

abgdf

Guru
Hallo,

... und in Python ungefähr so:
Code:
#!/usr/bin/env python
#-*- coding: iso-8859-1 -*-

import os
import shutil

MIXDIR = "/root/mix/"

def getMerkmal(a):

    fh = file(MIXDIR + a + "/" + a + ".txt", "r")
    b = fh.readlines()
    fh.close()

    for i in b:
        print i

        # Do something to fetch Merkmal
        m = i

    return m
    
l = os.listdir(MIXDIR)

for i in l:

    if os.access(MIXDIR + i + "/" + i + ".txt", os.F_OK):

        merkm = getMerkmal(i)

        if not os.path.isdir(MIXDIR + merkm):

            os.mkdir(MIXDIR + merkm)

            # os.sytem("mv " + MIXDIR + i + "/* " + MIXDIR + merkm)

            for u in os.listdir(MIXDIR + i):
                shutil.move(MIXDIR + i + "/" + u, MIXDIR + merkm)

            os.remove(MIXDIR +i)
Ungetestet.

Bitte erst verstehen, dann ändern, dann ggf. ausprobieren, denn es werden Dateien verschoben und gelöscht !

Gruß

P.S: Du solltest nicht als "root" arbeiten, das heißt normale Aufgaben durchführen.
 
OP
D

Daniel_SGE

Newbie
Hi! Danke! Ich werde beides bei Gelegenheit ausprobieren. Beim bash Skript, bin ich sehr zuversichtlich, dass es jetzt funktionieren wird...

Und zum Python-Skript, keine Angst, ich hatte ohnehin nicht vor, einfach irgendwelche Skripte auszuführen... Auf den 1. Blick scheint es mir doch im Gegensatz zum Bashskript sehr umfangreich und umständlich. Wenn ich das richtig verstanden habe, wäre aber der Vorteil eine plattformübergreifende Nutzbarkeit aufgrund des nicht direkt vorhandenen Compilers (korrigiert mich, wenn ich falsch liege;) ). Das käme mir sehr recht, da ich das Skript eigentlich (wie man vll. auch an den Leerzeichen merken kann ;) ) für Windows brauche, und es dann bei Bedarf auch direkt abrufen könnte :)

Gruß

Daniel
 

abgdf

Guru
Hi,

bash ist gut geeignet, wenn man mit Dateien arbeitet.
Will man Informationen aus Strings oder Textdateien ziehen, wird's aber ungemütlich, weil zu grob.
Perl und Python sind eben feiner und daher gut für solche Arbeit mit Textdateien geeignet. C ist sogar noch feiner. Da manipuliert man dann oft einzelne Bytes im Speicher.
Man muß eben sozusagen immer die richtige Nadel zum Stricken nehmen.

Doch, Python ist interpretiert. Python für Windows kann man kostenlos z.B. hier

http://www.activestate.com/Products/activepython/index.mhtml

herunterladen. Es lohnt sich.

Viele Grüße
 

Wizzzard

Member
@abgdf

Du verwendest in Deinem Skript das Zeichen '/' als Verzeichnistrenner. Wenn das auf anderen Systemen auch laufen soll, verwendet man besser os.path.join().
 

abgdf

Guru
Ah, danke !

Ich hacke sonst immer so herum ("hack-around" ist gar nicht so leicht zu übersetzen :)) :
Code:
if os.name == "posix":
    self.dslash = "/"

if os.name == "nt":
    self.dslash = "\\"
... obwohl Python für die Dateioperationen auch unter Windows "/" akzeptiert.

Viele Grüße
 
Oben