Jednym z podstawowych zadań systemu operacyjnego jest obsługa dyskowego systemu plików. Na poprzedniej lekcji omówiono funkcje Pythona służące do obsługi plików jako zbiorów danych, ich tworzenia i modyfikacji. W tym podrozdziale zostaną omówione funkcje służące do manipulacji plikami w całości, ich przenoszenia i usuwania oraz funkcje obsługujące katalogi dyskowe.
Funkcje, którymi będziemy się zajmować zawarte są w module standardowym os:
>>> from os import *
Aby sprawdzić, w jakim działamy obecnie katalogu dyskowym używamy funkcji getcwd:
>>> getcwd()
'C:\\Python24'
Aby zmienić bieżący katalog dyskowy na inny, używamy funkcji chdir(nowy katalog):
>>> chdir('tcl')
>>> getcwd()
'C:\\Python24\\tcl'
Aby poznać zawartość dowolnego katalogu dyskowego, używamy funkcji listdir(katalog); dla bieżącego katalogu:
>>> listdir('.')
['tcl84.lib', 'tclstub84.lib', 'tix8184.lib',
'tk84.lib', 'tkstub84.lib', 'tk8.4', 'tix8.1', 'tcl8.4', 'reg1.1', 'dde1.2']
Dla podkatalogu 'tcl8.4':
>>> listdir('tcl8.4')
['auto.tcl', 'history.tcl', 'init.tcl', 'ldAout.tcl',
'package.tcl', 'parray.tcl', 'safe.tcl', 'tclIndex', 'word.tcl', 'tcltest2.2',
'opt0.4', 'msgcat1.3', 'http2.4', 'http1.0', 'encoding']
Oczywiście, równie dobrze możemy podać ścieżkę absolutną katalogu:
>>> listdir(r'C:\Python24\tcl\tcl8.4')
['auto.tcl', 'history.tcl', 'init.tcl', 'ldAout.tcl',
'package.tcl', 'parray.tcl', 'safe.tcl', 'tclIndex', 'word.tcl', 'tcltest2.2', 'opt0.4',
'msgcat1.3', 'http2.4', 'http1.0', 'encoding']
Aby filtrować pliki i katalogi według określonego wzorca, musimy posłużyć się funkcją fnmatch(nazwa, wzorzec) z modułu fnmatch. Funkcja ta zwraca prawdę, wtedy i tylko wtedy, gdy nazwa odpowiada wzorcowi:
>>> import fnmatch
>>>
fnmatch.fnmatch('Python','P*n')
True
>>>
fnmatch.fnmatch('Python','P*e')
False
Lista plików z rozszerzeniem ‘tcl’:
>>> [x for x in
listdir(r'C:\Python24\tcl\tcl8.4') if \
fnmatch.fnmatch(x,'*.tcl')]
['auto.tcl', 'history.tcl',
'init.tcl', 'ldAout.tcl', 'package.tcl', 'parray.tcl', 'safe.tcl', 'word.tcl']
Lista plików o nazwach kończących się na ‘t’ lub ‘y’:
>>> [x for x in
listdir(r'C:\Python24\tcl\tcl8.4') if \
fnmatch.fnmatch(x,'*[ty].*')]
['history.tcl', 'init.tcl',
'ldAout.tcl', 'parray.tcl']
Zbliżony rezultat otrzymamy używając funkcji glob z modułu glob:
>>> for x in
glob.glob(r'C:\Python24\tcl\tcl8.4\*[ty].*'):
print x
C:\Python24\tcl\tcl8.4\history.tcl
C:\Python24\tcl\tcl8.4\init.tcl
C:\Python24\tcl\tcl8.4\ldAout.tcl
C:\Python24\tcl\tcl8.4\parray.tcl
Jak widać, ścieżki do znalezionych obiektów dyskowych zwracane są w takiej postaci, w jakiej podano jej we wzorcu (w tym przypadku absolutne). Aby rozdzielić ścieżkę absolutną na katalog zawierający plik i nazwę pliku używamy funkcji path.split:
>>>
path.split('C:\Python24\tcl\tcl8.4\history.tcl')
('C:\\Python24\tcl\tcl8.4',
'history.tcl')
>>> for x in
glob.glob(r'tcl8.4\*[ty].*'):
print path.split(x)[1]
history.tcl
init.tcl
ldAout.tcl
parray.tcl
Funkcja path.join łączy ciąg katalogów w ścieżkę:
>>>
path.join('C:','Python24','tcl','tcl8.4','history.tcl')
'C:Python24\\tcl\\tcl8.4\\history.tcl'
>>>
path.join(r'C:\Python24','tcl','tcl8.4\history.tcl')
'C:\\Python24\\tcl\\tcl8.4\\history.tcl'
Funkcja path.isabs sprawdza, czy podana ścieżka jest absolutna:
>>>
path.isabs(r'tcl8.4\history.tcl')
False
>>>
path.isabs(r'C:\Python24\tcl\tcl8.4\history.tcl')
True
Funkcja path.exists sprawdza, czy dany obiekt dyskowy istnieje:
>>>
path.exists('C:\\Python24\\tcl\\tcl8.4\\history.tcl')
True
>>>
path.exists('C:\\Python24\\tcl\\nowy')
False
Funkcja mkdir(nazwa katalogu) tworzy na dysku nowy katalog:
>>> mkdir('nowy')
>>> path.exists('C:\\Python24\\tcl\\nowy')
True
>>> listdir('.')
['tcl84.lib', 'tclstub84.lib',
'tix8184.lib', 'tk84.lib', 'tkstub84.lib', 'tk8.4', 'tix8.1', 'tcl8.4',
'reg1.1', 'dde1.2', 'nowy']
Funkcja rename(dotychczasowa nazwa, nowa nazwa) zmienia nazwę pliku lub katalogu:
>>>
rename('stary','nowy')
>>>
path.exists('C:\\Python24\\tcl\\nowy')
False
>>> listdir('.')
['tcl84.lib', 'tclstub84.lib',
'tix8184.lib', 'tk84.lib', 'tkstub84.lib', 'tk8.4', 'tix8.1', 'tcl8.4',
'reg1.1', 'dde1.2', 'stary']
Może także służyć do przenoszenia obiektów dyskowych pomiędzy katalogami:
>>>
file('plik','w').close()
>>> listdir('.')
['tcl84.lib', 'tclstub84.lib',
'tix8184.lib', 'tk84.lib', 'tkstub84.lib', 'tk8.4', 'tix8.1', 'tcl8.4', 'reg1.1',
'dde1.2', 'stary', 'plik']
>>>
rename('plik',r'stary\plik')
>>>
path.exists('C:\\Python24\\tcl\\plik')
False
>>>
path.exists('C:\\Python24\\tcl\\stary\\plik')
True
>>>
rename(r'stary\plik','plik')
>>>
path.exists('C:\\Python24\\tcl\\stary\\plik')
False
>>>
path.exists('C:\\Python24\\tcl\\plik')
True
Funkcja path.isfile sprawdza, czy dany obiekt dyskowy jest plikiem:
>>>
path.isfile('stary')
False
>>>
path.isfile('plik')
True
Funkcja path.isdir sprawdza, czy dany obiekt dyskowy jest katalogiem:
>>> path.isdir('plik')
False
>>> path.isdir('stary')
True
Funkcja path.ismount sprawdza, czy dany obiekt dyskowy jest dyskiem:
>>>
path.ismount('stary')
False
>>>
path.ismount('C:\\')
True
Funkcja path.getsize zwraca długość pliku w bajtach:
>>> path.getsize('plik')
0L
>>> f=file('plik','w'); f.write('Siedem!');
f.close()
>>> path.getsize('plik')
7L
>>> f=file('plik','w'); f.write('*'*100);
f.close()
>>> path.getsize('plik')
100L
Dla katalogów zwracane jest zawsze zero:
>>>
path.getsize('stary')
0L
>>> for x in
listdir('.'):
print x, path.getsize(x)
tcl84.lib 190886
tclstub84.lib 2272
tix8184.lib 49054
tk84.lib 165420
tkstub84.lib 2996
tk8.4 0
tix8.1 0
tcl8.4 0
reg1.1 0
dde1.2 0
stary 0
plik 100
Funkcja path.getctime zwraca czas stworzenia, a path.getmtime czas ostatniej modyfikacji obiektu dyskowego:
>>> from time import
ctime
>>>
ctime(path.getctime('plik'))
'Thu Oct 12 12:26:50 2006'
>>>
ctime(path.getmtime('plik'))
'Thu Oct 12 12:33:16 2006'
Funkcja walk(katalog nadrzędny, kolejność) służy do rekursywnego przechodzenia podanego katalogu wraz ze wszystkimi jego podkatalogami. Dla każdego znalezionego katalogu (łącznie z nadrzędnym) zwraca trójkę: (ścieżka, podkatalogi, pliki), gdzie ścieżka oznacza ścieżkę dostępu do katalogu, podkatalogi – listę nazw zawartych w nim podkatalogów, pliki – listę nazw zawartych w nim plików. Parametr kolejność (domyślnie True) ustawiony na False zwraca katalogi w odwrotnym porządku (zaczyna od najgłębiej położonego; może być to przydatne, jeżeli zamierzamy np. kasować podkatalogi).
>>> for sciezka, podkatalogi, pliki in
walk(r'C:\Python24\Tcl'):
print 'W
katalogu %s znajduje się %i bajtów w %i plikach' \
% (sciezka, sum(path.getsize(path.join(sciezka,
nazwa)) \
for nazwa in pliki), len(pliki))
W katalogu C:\Python24\Tcl znajduje się 410728 bajtów
w 6 plikach
W katalogu C:\Python24\Tcl\tk8.4 znajduje się 436678
bajtów w 30 plikach
W katalogu C:\Python24\Tcl\tk8.4\msgs znajduje się
51740 bajtów w 12 plikach
W katalogu C:\Python24\Tcl\tk8.4\images znajduje się
97217 bajtów w 13 plikach
W katalogu C:\Python24\Tcl\tk8.4\demos znajduje się
269352 bajtów w 54 plikach
W katalogu C:\Python24\Tcl\tk8.4\demos\images znajduje
się 277824 bajtów w 11 plikach
W katalogu C:\Python24\Tcl\tix8.1 znajduje się 596476
bajtów w 77 plikach
W katalogu C:\Python24\Tcl\tix8.1\pref znajduje się
236295 bajtów w 36 plikach
W katalogu C:\Python24\Tcl\tix8.1\bitmaps znajduje się
18805 bajtów w 58 plikach
W katalogu C:\Python24\Tcl\tcl8.4 znajduje się 121278
bajtów w 9 plikach
W katalogu C:\Python24\Tcl\tcl8.4\tcltest2.2 znajduje
się 98660 bajtów w 2 plikach
W katalogu C:\Python24\Tcl\tcl8.4\opt0.4 znajduje się
33631 bajtów w 2 plikach
W katalogu C:\Python24\Tcl\tcl8.4\msgcat1.3 znajduje
się 13083 bajtów w 2 plikach
W katalogu C:\Python24\Tcl\tcl8.4\http2.4 znajduje się
24706 bajtów w 2 plikach
W katalogu C:\Python24\Tcl\tcl8.4\http1.0 znajduje się
10494 bajtów w 2 plikach
W katalogu C:\Python24\Tcl\tcl8.4\encoding znajduje
się 1413736 bajtów w 78 plikach
W katalogu C:\Python24\Tcl\reg1.1 znajduje się 13182
bajtów w 2 plikach
W katalogu C:\Python24\Tcl\dde1.2 znajduje się 13646
bajtów w 2 plikach
W katalogu C:\Python24\Tcl\stary znajduje się 0 bajtów
w 0 plikach
Funkcja remove usuwa z dysku plik, a rmdir katalog o podanej nazwie:
>>> remove('plik')
>>>
path.exists('plik')
False
>>> rmdir('stary')
>>>
path.exists('stary')
False
Ćwiczenie 1. Napisz program, który znajdzie w podanym przez użytkownika katalogu i wszystkich jego podkatalogach wszystkie pliki, które zawierają podany przez użytkownika napis.
Ćwiczenie 2. Napisz program, który znajdzie w podanym przez użytkownika katalogu i wszystkich jego podkatalogach najstarszy i najdłuższy plik.
Ćwiczenie 3. Napisz program, który znajdzie w podanym przez użytkownika katalogu i wszystkich jego podkatalogach wszystkie zdublowane pliki, czyli takie pliki, których nazwa występuje jednocześnie w więcej niż jednym miejscu.