Co filesystem dal a vzal aneb m3uco.py skript je na světě

January 21st, 2008 by Jakub Lucký

Tuhle jsem se hrabal ve svých filesystémech a narazil jsem na jeden ze svých Python skriptů, pojmenovaný m3uco.py .

Historie

M3uco.py přišel na svět v létě 2007, v obci Hlohovec a Břeclav, jako práce pro Páju, který plánoval přechod na Linux (dosud neuskutečněný a už silně pochybuji, že k němu dojde, protože prostě proto) a m3ucopy měla být jedna z vychytávek, které mu ji měli umožnit

Z čeho to je?

Vezměte Python, jemně ho orestujte v editoru Eric3 (už ho nepoužívám), přidejte modul OptionParser, trošku něhy a lásky a máte to

Co to vlastně umí?

Uchopí to zadaný playlist (vycházel jsem ze syntaxe m3u, takže nějaké jiné to asi nemusí zvládat), a všechny jeho písničky zkopíruje do zadané lokace. K tomu to pochopitelně umí spoustu User-Friendly omáčky, možná pár bugů a podobně.

Samotný zdroják

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
#!/usr/bin/python# -- coding: utf-8 --#importy
import os.path
import shutil
import os
import sys
import re
from optparse import OptionParser#funkce pro pouze verbose výpis
 
def verbose(text):
    if options.verbose:
        print text
 
#Funkce na výpis pouze pokud není quiet
def notquiet(text):
    if not options.quiet:
        print text
 
#definice objektu parser, verze programu a popisu v --help
parser = OptionParser(usage="%prog [-sqnov] playlist destination/", version="%prog 0.1")
 
#Parametr na přepsání/nepřepsání souborů při kopírování
parser.add_option("-n", "--no-overwrite", action="store_true", dest="nooverwrite", help="Automatically denies ovewriting [default: %default]")
 
parser.add_option("-o", "--overwrite", action="store_true", dest="overwrite", help="Automatically overwrites existing files. [default: %default]")
 
#parametr pro minimum sdělovaných informací
parser.add_option("-q", "--quiet", action="store_true", dest="quiet", help="suppres any unneeded informations  [default: %default]")
 
# parametr na srovnání souborů podle playlistu
parser.add_option("-s", "--sort", action="store_true", dest="sort", help="Sort (Sort and rename files in same order as in playlist). [default: %default]")
 
# parametr pro víc informací pro uživatele
parser.add_option("-v", "--verbose", action="store_true", dest="verbose", help="Print additional informations while running. [default: %default]")
 
#načtení argumentů do options, argumentů do args
(options, args) = parser.parse_args()
 
#kontrola počtu argumentů, když nejsou dva, uživatel to zkonil a končí
if  len(args) != 2:
    print "Error! Invalid arguments! "
    sys.exit(1)
 
#Pokud je uživatel dement a chce verbose a quiet zároven
 
if options.verbose and options.quiet:
    print "Error! Can't be verbose and quiet at the same time!!"
    sys.exit(1)
 
#uložení parametrů do proměnných
 
playlist = os.path.abspath(args[0])
destination = os.path.abspath(args [1])
 
# Verbose informace
verbose("Using playlist: "+playlist)
verbose("Copying destination: "+destination)
verbose("---------------------------------------------------------------------------- \r\n")
 
#test jestli existuje playlist
 
if not os.path.isfile(playlist):
    print "zadaná cesta:" + playlist + " neexistuje!"
    sys.exit(1)
 
#test jestli existuje zadaná adresa
 
if not os.path.isdir(destination):
    print "zadaná cesta:" + destination + " neexistuje!"
    sys.exit(1)
 
#načtení playlistu do pole rows
 f = open(playlist)
rows = f.readlines()
 
#změna Working Directory aby seděli relativní cesty v playlistu
work_dir = os.path.dirname(playlist)
os.chdir(work_dir)
 
#vyrábíme pole pro uložení fileů
 
files=[]
 
#cyklus pro filtrovaní playlistu
 
for row in rows:
    #kontrola jestli řádek není komentář
    if re.match(r"^[^#].*$" ,row): #
 
    #kontrola jestli má řádek na konci \r\n jako konec řádku
    if re.match(r"^.*\r\n",row):
        i = len(row) - 2 #zajistíme proměnnou i pro zkrácení toho řádku o \r\n
        row = row[0:i] #zkrátíme row
 
    # stejně jako kontrola pro \r\n (jistící kontrola pro editory z jiných OS)
    if re.match(r"^.*\r",row) or re.match(r"^.*\n",row):
        i = len(row) - 1
        row = row[0:i]
 
#pokud ten soubor skutečně existuje, uložíme ho
 
if os.path.isfile(row):
    files.append(os.path.abspath(row))
 
#soubor neexistuje, sdělíme to uživateli
else:
    notquiet("File " + os.path.abspath(row) + " doesn't exist, therefore can't be copied")
 
#zkontrolujeme, je-li vůbec co kopírovat
if len(files) == 0:
    notquiet("No files to copy")
    sys.exit(0)
 
#zjištění řádu počtu kopírovaných souborů kvůli sortování
if options.sort:
    curr_length=len(files)
 
    #je jich min jak 10, nemá cenu to řešit
    if curr_length < 10:
        order=0
    #Je jich víc jak deset, budeme to řešit, default je jedna
    else:
        order=1
 
        #provede se, jen když jich bude víc jak sto
        while not curr_length/10 < 10 and curr_length/10 >= 1:
            order += 1
            curr_length = curr_length/10
 
         #vytvoření pole se sesortovanými názvy
         sorted_files=[]
 
         i = 1 #i je číslování
 
        #projde pole files, zkonvertuje
         for old_path in files:
            #Edituje starou cestu na novou
            new_path = os.path.dirname(old_path) + "/" + "0"*(order - (len(str(i))-1)) + str(i) + "_" + os.path.basename(old_path)
            #zapíše novou cestu do pole
            sorted_files.append(new_path)
            i +=1
        #proměnná kvůli určení fileu podle indexu
        sort_index = 0
 
#definice proměnné kvůli sort režimu v kombinaci s verbose
if options.verbose:
    old_wd = ""
 
#hlavní kopírovací cyklus
for file in files:
    #verbose info o adresáři
    if options.verbose:
        #kontrolujeme změnu kopírovacího adresáře (pokud je jiný, vypíšeme)
        if not old_wd == os.path.dirname(file):
            verbose("Currently copying from: "+ os.path.dirname(file) + "\r\n")
            old_wd = os.path.dirname(file)
    #proměnná kvůli kontrole existence (ochrana proti přepisu)
    if options.sort:
        copy_loc = sorted_files[sort_index]
    else:
         copy_loc = destination +"/"+ os.path.basename(file)
    #Soubor kam chceme kopírovat již existuje
    if os.path.exists(copy_loc):
        #uživatel zvolil parametr nepřepisovat
        if options.nooverwrite:
            notquiet("File: " + file + "  not copied! Name collision")
            continue
 
        #uživatel nezvolil parametr přepisovat, budeme se ptát
        elif not options.overwrite:
            #cyklus při kterém razantně čekáme odpověd
            while 1:
                if not options.sort:
                    answer = raw_input("File "+file +" exist in copying location! Do you like to overwrite it? [Y]es, [N]o or [R]ename ")
               else:
                    answer = raw_input("File "+os.path.basename(copy_loc) +" exist in copying location! Do you like to overwrite it? [Y]es, [N]o or [R]ename")
 
                #kontrola správnosti odpovědi
                if not answer in 'yYnNrR':
                    print "Wrong Answer! Repeat!"
                    continue
 
                 #odpověděl správně, konec cyklu
                else: break
 
                #chce to tam ale nechce přepisovat, tak přejmenujeme
                if answer and answer in "rR":
                    tmp_namer = 1
                     while 1:
                        copy_loc = copy_loc + "_" + str(tmp_namer)
                        if not os.path.exists(os.path.basename(copy_loc)):
                            verbose("Filename changed to: " + os.path.basename(copy_loc))
                            break
                        tmp_namer += 1
 
                elif not (answer and answer in 'yY'):
                    notquiet("File: " + file + " not copied! Name collision!!")
                    continue
 
               #odpověděl ano
               else:
                   notquiet("Overwritting file " + copy_loc + " !!")
                  #zvolil přepisovací parametr
              if options.overwrite:
                  notquiet("Overwritting file " + copy_loc + " !!")
 
              if options.sort:
                  sort_index += 1
 
              #pokusíme se o přepis
    try:
        shutil.copy(file,destination + "/" + os.path.basename(copy_loc))
        #verbose info navíc
        verbose("File: " + os.path.basename(file) + " ------- Succesfully copied!")
 
    except IOError:
        print "Error in copying file: "+ file

Zdrojový kód není úplně ideálně komentován, psal jsem ho v době, kdy jsem ještě neznal opravdu biblické Linusovy standardy a byl jsem ještě větší lamka než jsem, jak v Pythonu, tak v algoritmizaci obecně. Přesto si myslím, že si i fajnšmekři najdou to své, neboť jsem využil i pěkně skrytých funkcí Pythonu jako je násobič řetěžců a další.

Pro zájemce je zde i source-code ke stažení: m3ucopy

2 Responses to “Co filesystem dal a vzal aneb m3uco.py skript je na světě”

  1. Paja Says:

    S tou historií to není úplně přesné, neboť ses ptal, co by se mi hodilo napsat. Tak jsem navrhnul tohle, přechod na linux mi to nějak usnadnit nemělo. Druhá část, že jsem líné ***** a že přechod jsem měl maximálně zjednodušen a přesto jsem se nedokázal přizpůsobit je prostě moje chyba a Velká Programátorská Lenost. :-) Díky, že se kvůli tomu nerozčiluješ, přestože se ti to nelibí :)

  2. Danik Says:

    Paja je nase male roztomile prasatko.. :-)

Leave a Reply