python編程快速上手之第9章實踐項目參考答案


本章介介紹了shutil,zipfile模塊的使用,我們先來認識一下這2個模塊吧。

一.shutil模塊

shutil模塊主要用於對文件或文件夾進行處理,包括:復制,移動,改名和刪除文件,在shutil模塊中主要以下這么幾個函數:

1.復制文件和文件夾

shutil模塊提供了2個函數:shutil.copy()和shutil.copytree()

shutil.copy的語法格式:

copy(src, dst)

作用:

將src處的文件復制到dst路徑中去,其中src,dst都是字符串形式的路徑。如果dst是一個文件名,它將作為被復制文件的新名字,相當於把原路徑的文件復制到新路徑並改名。

舉例:

將/etc/my.cnf 復制到/root/mysql中

In [12]: import shutil In [13]: shutil.copy('/etc/my.cnf','/root/mysql/') Out[13]: '/root/mysql/my.cnf' In [15]: ll /root/mysql/ total 4
-rw-r--r--. 1 root 960 Apr 22 16:57 my.cnf

將/etc/my.cnf復制到/root/mysql並改名為mysql.cnf

In [16]: shutil.copy('/etc/my.cnf','/root/mysql/mysql.cnf') Out[16]: '/root/mysql/mysql.cnf' In [17]: ll /root/mysql/ total 8
-rw-r--r--. 1 root 960 Apr 22 16:57 my.cnf -rw-r--r--. 1 root 960 Apr 22 17:00 mysql.cnf

 

shutil.copytree的語法格式:

copytree(src, dst)

作用:

復制整個文件夾。將src處的文件夾,包括它的所有文件和子文件夾,復制到路徑dst處的文件夾。返回一個新復制的文件夾路徑的字符串。

舉例:

In [20]: shutil.copytree('/etc/yum.repos.d','/root/repo.back') Out[20]: '/root/repo.back' In [21]: ll /root/drwxr-xr-x. 2 root 4096 Apr 23  2017 repo.back/ drwxr-xr-x. 2 root 4096 Apr 23  2017 repo.bak/

注意:dst必須是一個系統中不存在目錄,不然會報錯:

In [20]: shutil.copytree('/etc/yum.repos.d','/root/repo.bak')
FileExistsError: [Errno 17] File exists: '/root/repo.bak'

2.文件和文件夾的移動和改名

shutil.move()

語法格式:

move(stc,dst)

作用:

將路徑stc處的文件夾移動到路徑dst,並返回新位置的絕對路徑的字符串。

舉例:

將/root/目錄下的a.txt移動到/root/test/目錄中

In [26]: shutil.move('/root/a.txt','/root/test/') Out[26]: '/root/test/a.txt' In [27]: ll /root/test total 4
-rw-r--r--. 1 root 6 Apr 22 17:30 a.txt

注意:

如果dst指向一個文件夾,src文件將移動到dst中,並保持原來的文件名,前提是dst必須是系統中已經存在的目錄。

如果目標文件中已存在相同名稱的文件將被覆蓋,需要注意。

3.刪除文件和文件夾

在os模塊中:

os.remove(path)可以刪除一個文件

os.rmdir(path)可以刪除一個空文件夾。

在shutil模塊中:

shutil.rmtree(path)可以刪除一個文件夾及其所有的內容。

語法格式:

os.rmdir(path) shutil.rmtree(path)

舉例:

 1 In [34]: os.remove('/root/test/a.txt')  2 
 3 In [35]: ll /root/test/
 4 total 0
 5 
 6 In [36]: shutil.move('/root/CentOS-Base.repo','/root/test/')  7 Out[36]: '/root/test/CentOS-Base.repo'
 8 
 9 In [37]: ll test 10 total 4
11 -rw-r--r--. 1 root 2573 Apr 23  2017 CentOS-Base.repo 12 
13 In [38]: shutil.rmtree('/root/test') 14 
15 In [39]: ll 16 total 12
17 -rw-------. 1 root 1468 Apr 16 21:03 anaconda-ks.cfg 18 drwxr-xr-x. 2 root   57 Apr 23  2017 download/
19 drwxr-xr-x. 2 root   37 Apr 22 17:00 mysql/
20 drwxr-xr-x. 6 root   95 Apr 16 21:58 py34/
21 drwxr-xr-x. 3 root   18 Apr 16 23:01 python/
22 drwxr-xr-x. 2 root 4096 Apr 23  2017 repo.back/
23 drwxr-xr-x. 2 root 4096 Apr 23  2017 repo.bak/

注意:

以上的刪除都是永久的刪除。為了安全起見最好使用send2trash第三方模塊,它會將刪除的文件放入回收站。在python3中已集成了這個模塊。

send2trash用法:

import send2trash
send2trash(path)

二.遍歷目錄樹

對文件的處理,尤其是批量操作就不得不對目錄進行遍歷。在python中os模塊中的os.walk()函數就可以做到。

這個函數會遞歸遍歷指定目錄及子目錄,返回一個3元組信息:當前目錄名,子目錄名,文件名,不包括 . 和 ..

常見用法:

#!/usr/bin/env python3.4
#coding:utf-8
import os
for foldName,subfolders,filenames in os.walk('/root/'):
    print('The current folder is: ' + foldName)
    for subfolder in subfolders:
        print('subfolder of ' + foldName + ':' + subfolder)
    for filename in filenames:
        print('file inside ' + foldName + ':' + filename)
    print('')

三.實踐項目參考答案

 1 #!/usr/bin/env python3.4
 2 # coding:utf-8
 3 import os  4 import shutil  5 import send2trash  6 
 7 # 9.8.1
 8 # 拷貝指定格式文件到指定目錄,下面程序是將/etc目錄下所的.conf文件拷貝到/root/test/目錄里。
 9 src = '/etc/'
10 dst = '/root/test/'
11 ftype = '.conf'
12 count = 0 13 for filename in os.listdir(src): 14     if filename.endswith(ftype): 15         shutil.copy(src + filename,dst) 16         count += 1
17         print('文件 ' + src + filename + '\t被拷貝到---> ' + dst + ' 目錄下') 18 print("該目錄下所有的 " + ftype + "文件已被拷貝到" + dst + "目錄下") 19 print('共拷貝了 ' + str(count) + ' 個文件') 20 
21 # 9.8.2
22 # 搜索指定目錄下大於100M的文件,打印出來並刪除
23 # 可以手動創建一個指定大小的空文件做試驗
24 # dd if=/dev/zero of=hello.txt bs=100M count=1
25 for foldname,subfolders,filenames in os.walk(dst): 26     for files in filenames: 27         if os.path.getsize(dst + files) / 1024 /1024 > 100: 28             print('大於100M的文件有:' + files + ' ' +  str(os.path.getsize(dst + files) / 1024 / 1024) +'Mb') 29             send2trash.send2trash(dst + files)

 9.8.3

假設test文件夾下有如下文件,文件是以spam開頭加上數字編號,但是編號並不連續有缺失,而且有的並不包含數字,我們需要找出不符合文件名的文件並重新命名成連續編號的文件名。

(py34) [root@master test]# ls
spam002.txt spam004.txt spam006.txt spam008.txt spam999.txt spam003.txt spam005.txt spam007.txt spam011.txt spamkkdf.txt

參考代碼如下:

 1 #!/usr/bin/env python3.4
 2 # coding:utf-8
 3 import re  4 import os  5 fdir = '/root/python/py-9/test/'
 6 fdir_list = os.listdir(fdir)  7 fdir_count = len(fdir_list)  8 print(fdir_list)  9 print('該目錄下共有 %d 個文件' %fdir_count) 10 f_pre = 'spam'
11 f_num = [] 12 f_end = '.txt'
13 fs_list = [] 14 # 這里只假定文件數量小100的情況
15 for i in range(1,fdir_count + 1): 16     if i < 10: 17         f_name = f_pre + '00' + str(i) + f_end 18         f_num.append('00' + str(i)) 19  fs_list.append(f_name) 20     else: 21         f_name = f_pre + '0' + str(i) + f_end 22         f_num.append('0' + str(i)) 23  fs_list.append(f_name) 24 max_f_num = max(f_num) 25 print('該目錄下文件最大的編號應該是: %s' %max_f_num) 26 print('正確的文件名應該是:') 27 print(fs_list) 28 
29 # 使用正則表達式搜索目錄中已有編號的文件並存入列表yf_num中
30 re_num = '\d{3}'
31 yf_num = re.findall(f_pre + re_num + f_end,' '.join(fdir_list)) 32 ra_num = re.findall(re_num,' '.join(fdir_list)) 33 print('目錄中已有編號文件:\n%s' %yf_num) 34 
35 # fq_list為目錄中缺失編號的文件名列表
36 # fx_list為當前目錄中需要修改名稱的文件列表
37 fq_list = [] 38 fx_list = [] 39 # 定位缺失的編號文件並放入列表中
40 for a in fs_list: 41     if a not in yf_num: 42  fq_list.append(a) 43 print('缺少的文件編號是:\n%s' %fq_list) 44 
45 # 查找目錄中沒有編號或不正連續的編號文件並放入列表中
46 for f_rename in fdir_list: 47     if f_rename not in fs_list: 48  fx_list.append(f_rename) 49 print('需要修改的文件名有:\n%s' %fx_list) 50 
51 # 更改文件名
52 for k in fq_list: 53     for v in fx_list: 54         os.rename(fdir + v,fdir + k) 55         # 每當修完一個文件名應該更新一下這個列表
56  fx_list.remove(v) 57 print('改完名后的結果為:') 58 os.system('ls')

今天回來看看,決定用函數的方式來練習並實現,代碼有了一些小的改進,上代碼:

 1 #!/usr/bin/env python3.4
 2 # coding:utf-8
 3 import re  4 import os  5 fdir = '/root/github/shell/python3/py-9/test/'
 6 fdir_list = os.listdir(fdir)  7 fdir_f_count = len(fdir_list)  8 print('當前目錄的文件為:\n%s' % fdir_list)  9 def getFileformat(f_pre,f_num,f_end): 10     fileformat = f_pre + f_num + f_end 11     return fileformat 12 file_list = [] 13 def getTruefile(): 14     for i in range(1,fdir_f_count + 1): 15         if i < 10: 16             f_format = getFileformat('spam','00' + str(i),'.txt') 17  file_list.append(f_format) 18         else: 19             f_format = getFileformat('spam','0' + str(i),'.txt') 20  file_list.append(f_format) 21     return file_list 22 truefilelist = getTruefile() 23 print('正確的文件編號應該是:\n%s' %truefilelist) 24 lostnumfilelist = [] 25 def getLostnumfile(fdirlist,truelist): 26     for lf in truelist: 27         if lf not in fdirlist: 28  lostnumfilelist.append(lf) 29     return lostnumfilelist 30 lostnumfile = getLostnumfile(fdir_list,file_list) 31 print('缺失的文件編號為:\n%s' %lostnumfile) 32 
33 renamelist = [] 34 def getrenamefile(fdirlist,func): 35     for a in fdirlist: 36         if a not in func: 37  renamelist.append(a) 38     return renamelist 39 renamefilelist = getrenamefile(fdir_list,file_list) 40 print('需要修改的文件是\n%s' %renamefilelist) 41 
42 def renamefile(func1,func2): 43     for b in func1: 44         for c in func2: 45             os.rename(fdir + c,fdir + b) 46  func2.remove(c) 47 rename = renamefile(lostnumfile,renamefilelist) 48 os.chdir(fdir) 49 print('修改后的結果為:') 50 os.system('ls')

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM