Programm in Ordner suchen

Wenn du dir nicht sicher bist, in welchem der anderen Foren du die Frage stellen sollst, dann bist du hier im Forum für allgemeine Fragen sicher richtig.
Antworten
JakobPrie
User
Beiträge: 91
Registriert: Sonntag 21. Juni 2020, 11:12

Hallo,
ich möchte ein Skript schreiben, welches ein Programm auf dem Rechner anhand eines eingegebenen Strings sucht und bei einem Treffer dieses ausführt. dafür gebe ich als String den Namen an und gegebenenfalls die Datei-Endung. In den program_paths werden alle Pfade angegeben, in welchen Programme installiert werden.
Dafür habe ich mal folgendes geschrieben:

Code: Alles auswählen

    def __init__(self):
        self.program_paths = program_paths
        self.open_program_done = False

Code: Alles auswählen

    def open(self, program_name, ending='exe'):
        for item in program_paths:
            finder = Thread(target=self.find_files(self, program_name, item, ending))
            finder.daemon = True
            finder.start()

Code: Alles auswählen

    def find_files(self, program_name, root, ending):
        for root, dirs, files in os.walk(root):
            for f in files:
                if f.lower().endswith(ending) and program_name.lower() in f.lower():
                    f = os.path.join(root, f)
                    print(f)
                    temp_name = program_name + "." + ending
                    if temp_name == f:
                        subprocess.Popen(f)
                if open_program_done:
                    break
            if not open_program_done:
                for d in dirs:
                    d = os.path.join(root, d)
                    self.find_files(self, d, ending, ending)
            else:
                break
Damit das ganze nicht zu lange dauert habe ich mit Threads gearbeitet. Allerdings ist meine Plazierung, bzw Umsetzung von open_program_done absolut falsch. Meine Idee war es, dass der finder aufhört, wenn bereits eine Datei mit dem richtigen Namen gefunden wurde.
Vielen Dank für Eure Hilfe!
Sirius3
User
Beiträge: 18272
Registriert: Sonntag 21. Oktober 2012, 17:20

Statt os.walk und os.path.join sollte man pathlib.Path.rglob benutzen.
temp_name kann nie gleich f sein. open_program_done ist nicht definiert.
Die for-d-in-dirs-Schleife ist unsinnig, da das schon os.walk, bzw. pathlib.Path.rglob erledigt.
Einem Thread wird per target eine Funktion übergeben, nicht der Rückgabewert des Aufrufs einer Funktion. `find_files` wird ein Argument zu viel übergeben. `program_paths` wird nirgends definiert.

Bevor Du anfängst, eine ganze Klasse mit mehreren Methoden zu schreiben, solltest Du die einzelnen Teile erst ausgiebig testen.
Sirius3
User
Beiträge: 18272
Registriert: Sonntag 21. Oktober 2012, 17:20

Nochmal ich: eine Funktion die find_files heißt, sollte nicht ein Programm ausführen, sondern tatsächlich nur die gefundenen Stellen zurückgeben.
Das ganze ohne die Klasse (die im Moment noch unnötig ist):

Code: Alles auswählen

from pathlib import Path

def find_files(program_paths, program_name, ending=".exe"):
    found_program_paths = []
    program_name += ending
    for path in program_paths:
        found_program_paths.extend(Path(path).rglob(program_name))
    return found_program_paths 
JakobPrie
User
Beiträge: 91
Registriert: Sonntag 21. Juni 2020, 11:12

Sirius3 hat geschrieben: Donnerstag 17. September 2020, 07:19 Nochmal ich: eine Funktion die find_files heißt, sollte nicht ein Programm ausführen, sondern tatsächlich nur die gefundenen Stellen zurückgeben.
Das ganze ohne die Klasse (die im Moment noch unnötig ist):

Code: Alles auswählen

from pathlib import Path

def find_files(program_paths, program_name, ending=".exe"):
    found_program_paths = []
    program_name += ending
    for path in program_paths:
        found_program_paths.extend(Path(path).rglob(program_name))
    return found_program_paths 
Vielen Dank für Deine Hilfe!
JakobPrie
User
Beiträge: 91
Registriert: Sonntag 21. Juni 2020, 11:12

Sirius3 hat geschrieben: Donnerstag 17. September 2020, 07:19 Nochmal ich: eine Funktion die find_files heißt, sollte nicht ein Programm ausführen, sondern tatsächlich nur die gefundenen Stellen zurückgeben.
Das ganze ohne die Klasse (die im Moment noch unnötig ist):

Code: Alles auswählen

from pathlib import Path

def find_files(program_paths, program_name, ending=".exe"):
    found_program_paths = []
    program_name += ending
    for path in program_paths:
        found_program_paths.extend(Path(path).rglob(program_name))
    return found_program_paths 
Lassen sich mit diesem Algorithmus auch Verknüpfungen finden? Bei mir hat das gerade nicht ganz geklappt

Kann ich den Algorithmus alternativ auch irgendwie umbauen, dass auch Treffer gedunden werden, in welchen der Programm-name nur vorkommt? Weil das exe von Word heißt WINWORD.EXE, ich suche aber nach dem Programm_namen "word"
Jankie
User
Beiträge: 592
Registriert: Mittwoch 26. September 2018, 14:06

Verknüpfungen funktionieren bei mir, da musst du das ending halt nur auf ".lnk" setzen. Und bitte nicht immer die Beiträge zitieren.

Code: Alles auswählen

print(find_files([r"C:\Users\xxx\Desktop"], "TEST", ending=".lnk"))
Und so zeigt er mit alle .bmp an die "Neue" im Namen haben (Bin mir aber nicht sicher, ob es bessere Möglichkeiten gibt):

Code: Alles auswählen

from pathlib import Path

def find_files(program_paths, program_name, ending=".exe"):
    found_program_paths = []
    for path in program_paths:
        for pattern in [f"*{program_name}*", f"{program_name}*", f"*{program_name}"]:
            found_program_paths.extend(Path(path).rglob(pattern))
    return found_program_paths 


print(find_files([r"C:\Users\xxx\Desktop"], "Neue", ending=".bmp"))
Jankie
User
Beiträge: 592
Registriert: Mittwoch 26. September 2018, 14:06

Gerade gemerkt das dort das ending nicht beachtet wird, hier noch mal, aber nun mit Berücksichtigung des endings.

Code: Alles auswählen

from pathlib import Path

def find_files(program_paths, program_name, ending=".exe"):
    found_program_paths = []
    for path in program_paths:
        for pattern in [f"*{program_name}*{ending}", f"{program_name}*{ending}", f"*{program_name}{ending}"]:
            found_program_paths.extend(Path(path).rglob(pattern))
    return found_program_paths 


print(find_files([r"C:\Program Files"], "pad", ending=".exe"))
Sirius3
User
Beiträge: 18272
Registriert: Sonntag 21. Oktober 2012, 17:20

@Jankie: * bedeutet "beliebig viele Zeichen" und beliebig viele sind auch 0, so dass alle weiteren Pattern schon mit dem ersten abgedeckt sind.
Bei der Verallgemeinerung sind die Variablennamen verwirrend.

Code: Alles auswählen

def find_files(paths, filename_part, ending=""):
    found_paths = []
    for path in paths:
        found_paths .extend(Path(path).rglob(f"*{filename_part}*{ending}"))
    return found_paths 
Benutzeravatar
__blackjack__
User
Beiträge: 14052
Registriert: Samstag 2. Juni 2018, 10:21
Wohnort: 127.0.0.1
Kontaktdaten:

Kleine Warnung: Wenn man mit "word" auch "winword.exe" finden will, kann es natürlich passieren, dass man auch "wordpad.exe" findet. Wie wird dann entschieden welches davon gestartet wird‽
“Vir, intelligence has nothing to do with politics!” — Londo Mollari
JakobPrie
User
Beiträge: 91
Registriert: Sonntag 21. Juni 2020, 11:12

__blackjack__ hat geschrieben: Donnerstag 17. September 2020, 13:50 Kleine Warnung: Wenn man mit "word" auch "winword.exe" finden will, kann es natürlich passieren, dass man auch "wordpad.exe" findet. Wie wird dann entschieden welches davon gestartet wird‽
Ich habe eine alternative lösung gefunden:
Und zwar such eich einfach in dem Ordner C:\ProgramData\Microsoft\Windows\Start Menu\Programs, in welchem Verknüpfungen zu allen programmen, die ich benötige sind. Da muss ich mir auch keine Gedanken um den Namen der datei machen, da hier nutzerfreundliche genommen werden.
Aber danke an alle für die Hilfe
JakobPrie
User
Beiträge: 91
Registriert: Sonntag 21. Juni 2020, 11:12

Sirius3 hat geschrieben: Donnerstag 17. September 2020, 07:19 Nochmal ich: eine Funktion die find_files heißt, sollte nicht ein Programm ausführen, sondern tatsächlich nur die gefundenen Stellen zurückgeben.
Das ganze ohne die Klasse (die im Moment noch unnötig ist):

Code: Alles auswählen

from pathlib import Path

def find_files(program_paths, program_name, ending=".exe"):
    found_program_paths = []
    program_name += ending
    for path in program_paths:
        found_program_paths.extend(Path(path).rglob(program_name))
    return found_program_paths 
Wie kann ich diesen Algorithmus umbauen, dass er sobald er einen Pfad gefunden hat, abbricht?
JakobPrie
User
Beiträge: 91
Registriert: Sonntag 21. Juni 2020, 11:12

Sirius3 hat geschrieben: Donnerstag 17. September 2020, 07:19 Nochmal ich: eine Funktion die find_files heißt, sollte nicht ein Programm ausführen, sondern tatsächlich nur die gefundenen Stellen zurückgeben.
Das ganze ohne die Klasse (die im Moment noch unnötig ist):

Code: Alles auswählen

from pathlib import Path

def find_files(program_paths, program_name, ending=".exe"):
    found_program_paths = []
    program_name += ending
    for path in program_paths:
        found_program_paths.extend(Path(path).rglob(program_name))
    return found_program_paths 
Wie kann ich diesen Algorithmus umbauen, dass er sobald er einen Pfad gefunden hat, abbricht?
Sirius3
User
Beiträge: 18272
Registriert: Sonntag 21. Oktober 2012, 17:20

@JakobPrie: was denkst Du, wie man das umschreiben kann?
Antworten