2013-11-27 5 views
6

Ich versuche, ein Programm zu schreiben, das ein Befehlszeilenargument verwendet, den durch das Argument bereitgestellten Verzeichnisbaum durchsucht und eine Liste aller Dateien im Verzeichnis erstellt und sortiert nach Länge der Dateien.Abrufen von Dateien aus Verzeichnisargument, Sortieren nach Größe

Ich bin nicht viel von einem Skript-Kerl - aber das ist, was ich habe und es funktioniert nicht:

import sys 
import os 
from os.path import getsize 

file_list = [] 

#Get dirpath 
dirpath = os.path.abspath(sys.argv[0]) 
if os.path.isdir(dirpath): 
    #Get all entries in the directory 
    for root, dirs, files in os.walk(dirpath): 
     for name in files: 
      file_list.append(name) 
     file_list = sorted(file_list, key=getsize) 
     for item in file_list: 
      sys.stdout.write(str(file) + '\n') 

else: 
    print "not found" 

jemand mich in die richtige Richtung zeigen kann?

+0

ich schlage vor, die Hilfe für die Funktion zu lesen [ 'o s.walk'] (http://docs.python.org/2/library/os.html#os.walk). Es scheint die richtige Wahl für den Umgang mit Verzeichnisbäumen zu sein. Wenn Sie sich das Beispiel für diese Funktion ansehen, werden Sie sehen, dass Sie auf einem guten Weg sind ... – koffein

+0

Ich denke, Ihre vorletzte Zeile ist nicht notwendig. tatsächlich verursacht diese Linie einen Fehler ... – koffein

+0

@koffein Ich habe meinen Code aktualisiert, aber es gibt mir immer noch einen Fehler. –

Antwort

6

Hoffentlich hilft Ihnen diese Funktion (ich benutze Python 2.7):

+1

Ich lese das mehrmals und ich sehe es funktioniert, aber ich habe auch bemerkt, dass Sie nicht alle kleinen Dinge entdeckt haben, die Ihren Python-Code schöner machen und lesbar. Ich hoffe, Sie schätzen einige Ratschläge: Wann immer Sie denken, dass Sie schreiben müssen "für i in Bereich (len (some_list))", verwenden Sie ['enumerate'] (http://docs.python.org/2/library/functions .html # enumerate) statt. Wenn Sie eine Liste neu füllen möchten, lassen Sie Ihre "Array-Denkweise" fallen, versuchen Sie stattdessen etwas wie folgt: 'lst = [do_something (entry) für Eintrag in lst]' ... – koffein

+2

Aber wenn Sie a generieren Liste, die Sie ohne weitere Verwendung wieder auffüllen möchten, denken über die Verwendung von Generatoren nach. Sie müssen also nicht immer wieder über eine Liste iterieren ...spart Speicher, Zeit ... Wenn Sie es leid sind, lesen Sie dieses Video ... nach Jahren der Programmierung in Python sah ich mit meinem Mund weit geöffnet! [Umwandlung von Code in schöne, Idiomatische Python] (https://www.youtube.com/watch?v=OSGv2VnC0go) – koffein

+0

'dirname' ist ein reservierter Name für eine Funktion in' os.path', sollten Sie nicht verwenden als Variablenname in Ihrem Skript. Die Funktion funktioniert super BTW! – Gabriel

0

Sie extrahieren den Befehl und nicht das erste Argument mit argv[0]; verwenden argv[1] dafür:

dirpath = sys.argv[1] # argv[0] contains the command itself. 

Aus Performance-Gründen schlage ich vor, Sie die Dateigrößen Prefetch anstelle der OS über die Größe der gleichen Datei mehrmals während des Sortierens zu fragen (wie durch Koffein vorgeschlagen, os.walk ist der Weg zu go):

files_list = [] 
for path, dirs, files in os.walk(dirpath)): 
    files_list.extend([(os.path.join(path, file), getsize(os.path.join(path, file))) for file in files]) 

Sie nicht die unsortierte Liste benötigen Unter der Annahme, werden wir die Vor-Ort-Art() -Methode:

files_list.sort(key=operator.itemgetter(1)) 
+0

die 'files'-liste ist nur eine liste der dateinamen, oder? Ich denke, dass Sie die 'Datei'-Namen mit' Pfad' verbinden müssen – koffein

5

Dies ist ein Ansatz mit Generatoren. Sollte für große Anzahl von Dateien schneller ...

Dies ist der Beginn der beiden Beispiele:

import os, operator, sys 
dirpath = os.path.abspath(sys.argv[0]) 
# make a generator for all file paths within dirpath 
all_files = (os.path.join(basedir, filename) for basedir, dirs, files in os.walk(dirpath) for filename in files ) 

Wenn Sie nur eine Liste der Dateien, ohne die Größe möchten, können Sie diese verwenden:

sorted_files = sorted(all_files, key = os.path.getsize) 

Aber wenn Sie Dateien und Pfade in einer Liste möchten, können Sie diese verwenden:

# make a generator for tuples of file path and size: ('/Path/to/the.file', 1024) 
files_and_sizes = ((path, os.path.getsize(path)) for path in all_files) 
sorted_files_with_size = sorted(files_and_sizes, key = operator.itemgetter(1)) 
+0

Verwenden Sie 'sorted_files_with_size.reverse()', um zuerst die größten Dateien anzuzeigen. Dies ist ziemlich schnell und ist nützlich, um eine schnelle Vorstellung davon zu bekommen, welche Dateien Platz beanspruchen. –

Verwandte Themen