Python中的檔案和目錄操作實現代碼

來源:互聯網
上載者:User
本文將詳細解釋這些函數的使用方法。首先,我們介紹Python語言中類似於Windows系統的dir命令的列出檔案功能,然後描述如何測試一個檔案名稱對應的是一個標準檔案、目錄還是連結,以及提取檔案大小和日期的方法。之後,我們還將介紹如何刪除檔案和目錄,如何複製和刪除檔案,以及怎樣將一個完整的檔案路徑分解成目錄部分和檔案名稱部分,最後,我們講解目錄的建立,以及如何在分類樹中移動目錄並處理檔案。
  一、顯示目錄內容
  當我們想要列出目前的目錄中所有副檔名為.jpg或.gif的檔案的時候,就可以使用glob模組來完成此項任務,如下所示:
  import glob
  filelist = glob.glob('*.jpg') + glob.glob('*.gif')
  上述代碼使用了glob函數,該函數的參數為要顯示的檔案類型。在這裡,檔案類型是通過類似UNIX作業系統shell風格萬用字元描述的一些檔案名稱來指定的。這些萬用字元的使用方法,具體請參考fnmatch模組的文檔,那裡有具體的說明和樣本。
  為了顯示一個目錄中的全部檔案,可以使用如下所示的os.listdir函數:

代碼如下:


  files = os.listdir(r'C:\hpl\scripting\src\py\intro') #適用於 Windows
  files = os.listdir('/home/hpl/scripting/src/py/intro') # 適用於Unix
  # 跨平台版本:
  files = os.listdir(os.path.join(os.environ['scripting'],
  'src', 'py', 'intro'))
  files = os.listdir(os.curdir) # 目前的目錄中的所有檔案
  files = glob.glob('*') + glob.glob('.*')


  二、測試檔案類型
  我們知道,檔案名稱、目錄名和連結名都是用一個字串作為其標識符的,但是給我們一個標識符,我們該如何確定它所指的到底是常規檔案檔案名稱、目錄名還是連結名呢?這時,我們可以使用os.path模組提供的isfile函數、isdir函數和islink函數來達成我們的目標,如下所示:
  

代碼如下:


print myfile, '是一個',
  if os.path.isfile(myfile):
  print 'plain file'
  if os.path.isdir(myfile):
  print 'directory'
  if os.path.islink(myfile):
  print 'link'


  您還可以尋找檔案的日期及其大小:

代碼如下:


  time_of_last_access = os.path.getatime(myfile)
  time_of_last_modification = os.path.getmtime(myfile)
  size = os.path.getsize(myfile)


  這裡的時間以秒為單位,並且從1970年1月1日開始算起。為了擷取以天為單位的最後訪問日期,可以使用下列代碼:
  import time # time.time()返回目前時間
  age_in_days = (time.time()-time_of_last_access)/(60*60*24)
  為了擷取檔案的詳細資料,可以使用os.stat函數和stat模組中的其它公用程式來達到目的,如下:

代碼如下:


  import stat
  myfile_stat = os.stat(myfile)
  size = myfile_stat[stat.ST_SIZE]
  mode = myfile_stat[stat.ST_MODE]
  if stat.S_ISREG(mode):
  print '%(myfile)是一個常規檔案,大小為 %(size)d 位元組' %\
  vars()


  有關stat模組的詳細資料,請參見Python Library Reference。若想測試一個檔案的讀、寫以及執行許可權,可以用os.access函數,具體如下所示:
  if os.access(myfile, os.W_OK):
  print myfile, '具有寫入權限'
  if os.access(myfile, os.R_OK | os.W_OK | os.X_OK):
  print myfile, '具有讀、寫以及執行許可權'
  像上面這樣的測試代碼,對CGI指令碼來說非常有用。
  三、檔案和目錄的刪除
  若要刪除單個檔案的話,可以使用os.remove函數,例如:os.remove('mydata.dat')。Os.remove的別名是os.unlink,不過後者跟傳統的UNIX作業系統以及Perl中清除檔案的函數重名。我們可以使用下列方式來刪除一組檔案,如所有以.jpg以及*.gif為副檔名的檔案:
  for file in glob.glob('*.jpg') + glob.glob('*.gif'):
  os.remove(file)
  大家知道,只有當目錄中內容已經被清空的時候,我們才可以使用rmdir命令來刪除該目錄。不過,我們經常想要刪除一個含有許多檔案的分類樹,這時我們可以使用shutil模組提供的rmtree函數,如下所示:
  shutil.rmtree('mydir')
  它相當於UNIX作業系統中的命令rm -rf mydir。
  我們可以建立一個自訂函數,使其在進行刪除操作的時候將檔案和目錄做同等對待,其典型用法如下所示:
  remove('my.dat') #刪除當個檔案my.dat
  remove('mytree') #刪除單個分類樹 mytree
  # 通過字串列表中的名稱來刪除多個檔案/分類樹:
  remove(glob.glob('*.tmp') + glob.glob('*.temp'))
  remove(['my.dat','mydir','yourdir'] + glob.glob('*.data'))
  下面是remove函數的實現:
  def remove(files):
  """刪除一個或多個檔案和/或目錄。"""
  if isinstance(files, str): # files是個字串嗎?
  files = [files] # 把files從字串轉為列表
  if not isinstance(files, list): # files不是列表嗎?
  
  for file in files:
  if os.path.isdir(file):
  shutil.rmtree(file)
  elif os.path.isfile(file):
  os.remove(file)
  下面測試一下remove函數的靈活性:

代碼如下:


  # 建立10個目錄tmp_* ,以及10各檔案tmp__*:
  for i in range(10):
  os.mkdir('tmp_'+str(i))
  f = open('tmp__'+str(i), 'w'); f.close()
  remove('tmp_1') # tmp_1為目錄
  remove(glob.glob('tmp_[0-9]') + glob.glob('tmp__[0-9]'))


  作為上述remove函數實現的一個註記,我們進行了下列測試:
  if not isinstance(files, list):
  它實際上是過於嚴厲。我們需要的只是一個被遍曆的一個檔案/目錄名序列。實際上,我們並不關心名稱是否儲存在一個列表、元組或者數值數組中,所以更好的測試應該像下面這樣:
  if not operator.isSequenceType(files):
  
  四、檔案的複製與重新命名
  當我們要複製檔案的時候,可以使用shutil模組:
  import shutil
  shutil.copy(myfile, tmpfile)
  #拷貝最後訪問時間和最後修改時間:
  shutil.copy2(myfile, tmpfile)
  # 拷貝一個分類樹:
  shutil.copytree(root_of_tree, destination_dir, True)
  Copytree的第三個參數規定對符號連結的處理,其中True表示保留符號連結;而False則意味著使用檔案的物理副本替代符號連結。
  Python語言能夠很好地支援路徑名的跨平台組成:Os.path.join能使用正確的分界符(在UNIX和Mac OS X作業系統中使用/,在 Windows 上使用\)來聯結目錄和檔案名稱,變數os.curdir和os.pardir分別表示當前工作目錄及其父目錄。 像下面的UNIX作業系統命令
  cp http://www.bitsCN.com/f1.c .
  可以使用Python語言提供一個跨平台的實現:
  shutil.copy(os.path.join(os.pardir,os.pardir,'f1.c'), os.curdir)
  Os模組中的rename函數通常被用於重新命名一個檔案:
  os.rename(myfile, 'tmp.1') # 將myfile重新命名為'tmp.1'
  這個函數也可用來在相同的檔案系統之內移動檔案。這裡,我們將myfile移動到目錄d下面:
  os.rename(myfile, os.path.join(d, myfile))
  在跨檔案系統移動檔案的時候,可以先使用shutil.copy2來複製檔案,然後再刪除原來的副本即可,如下:
  shutil.copy2(myfile, os.path.join(d, myfile))
  os.remove(myfile)
  後面這種移動檔案的方法是最安全的。
  五、分解路徑名
  假設我們使用變數fname來存放一個包含完整路徑的檔案名稱,例如:
  /usr/home/hpl/scripting/python/intro/hw.py
  有時候,我們需要將這樣的檔案路徑拆分為基本名稱hw.py和目錄名/usr/home/hpl/scripting/python/intro。在Python語言中,可以使用下列代碼達到目的:
  basename = os.path.basename(fname)
  dirname = os.path.dirname(fname)
  # 或
  dirname, basename = os.path.split(fname)
  副檔名是通過os.path.splitext函數提取出來的,
  root, extension = os.path.splitext(fname)
  這樣,fname中的副檔名部分即.py被賦給變數extension,而其餘部分則賦給了變數root。如果想得到不帶點號的副檔名的話,只需使用os.path.splitext(fname)[1][1:]即可。
  假設一個檔案名稱為f,其副檔名隨意,若想將其副檔名改為ext,可以使用下面的代碼:
  newfile = os.path.splitext(f)[0] + ext
  下面是一個具體的樣本:
  >>> f = '/some/path/case2.data_source'
  >>> moviefile = os.path.basename(os.path.splitext(f)[0] + '.mpg')
  >>> moviefile
  'case2.mpg'
  六、目錄的建立和移動
  Os模組中的函數mkdir可以用來建立目錄,而chdir函數則可以移動目錄,如下:
  origdir = os.getcwd() # 將當前位置記下來
  newdir = os.path.join(os.pardir, 'mynewdir')
  if not os.path.isdir(newdir):
  os.mkdir(newdir) # 或者os.mkdir(newdir,'0755')
  os.chdir(newdir)
  ...
  os.chdir(origdir) # 返回原目錄
  os.chdir(os.environ['HOME']) # 移到主目錄
  假設我們想要在自己的主目錄下建立一個新目錄py/src/test1,但是目前py、src和test1都不存在。如果使用mkdir命令來建立的話,需要使用三次才能建好這個嵌套的目錄,但是使用Python語言提供的os.makedirs命令的話,則無需這樣麻煩了,該命令可以一次建好整個目錄:
  os.makedirs(os.path.join(os.environ['HOME'],'py','src','test1'))
  七、遍曆分類樹
  下面的函數調用
  os.path.walk(root, myfunc, arg)
  將遍曆root分類樹;然後,對每個目錄名dirname分別調用myfunc(arg, dirname, files)即可,這裡參數files是dir中的檔案名稱列表(可通過調用os.listdir(dirname)來獲得);arg是使用者從調用代碼中傳遞來的參數。對於UNIX作業系統使用者來說,Python語言中跨平台的os.path.walk相當於Unix命令find。
  在解釋os.path.walk的用法的時候,人們常使用寫出主目錄中所有子目錄內的檔案的名稱為例進行說明。當然,我們也可以在一個互動Python命令列中使用下列程式碼片段來體會os.path.walk的使用:
  def ls(arg, dirname, files):
  print dirname, 'has the files', files
  os.path.walk(os.environ['HOME'], ls, None)
  本例中,參數arg並非必需,所以在os.path.walk調用中讓其取值為None即可。
  為了列出主目錄中所有大於1Mb的檔案,可以使用下面的代碼:
  def checksize1(arg, dirname, files):
  for file in files:
  filepath = os.path.join(dirname, file)
  if os.path.isfile(filepath):
  size = os.path.getsize(filepath)
  if size > 1000000:
  size_in_Mb = size/1000000.0
  arg.append((size_in_Mb, filename))
  bigfiles = []
  root = os.environ['HOME']
  os.path.walk(root, checksize1, bigfiles)
  for size, name in bigfiles:
  print name, '大小為', size, 'Mb'
  現在,我們使用arg來建立一個資料結構,這裡是一個2元組構成的列表,其中每個2元組存放檔案的尺寸(以MB為單位)和完整的檔案路徑。如果用於所有目錄的函數調用中都要更改arg的話,那麼arg必須是一個可變的資料結構,即允許適當地進行修改。
  參數dirname是當前正在訪問的目錄的絕對路徑,而參數files內的檔案名稱則是相對於dirname的相對路徑。在此期間,當前工作目錄並沒有改變,那就是說該指令碼仍然呆在指令碼啟動時刻所在的目錄中。這就是為什麼我們需要把filepath弄成帶有dirname和file的絕對路徑的原因。若要改變當前工作目錄為dirname,只要在針對每個目錄調用os.path.walk的函數中調用一下os.chdir(dirname),然後在該函數的末尾重新調用os.chdir(dirname)將當前工作目錄改回原值即可,如下所示:
  def somefunc(arg, dirname, files):
  origdir = os.getcwd(); os.chdir(dirname)
  
  os.chdir(origdir)
  os.path.walk(root, somefunc, arg)
  當然,如果您願意也可以編寫具有類似功能的代碼來替代os.path.walk。下面的代碼,將針對每個檔案而非每個目錄來調用的自訂函數,如下所示:
  def find(func, rootdir, arg=None):
  # 對rootdir目錄中的每個檔案調用func
  files = os.listdir(rootdir) # 擷取rootdir目錄中的所有檔案
  files.sort(lambda a, b: cmp(a.lower(), b.lower()))
  for file in files:
  fullpath = os.path.join(rootdir, file)
  if os.path.islink(fullpath):
  pass
  elif os.path.isdir(fullpath):
  find(func, fullpath, arg)
  elif os.path.isfile(fullpath):
  func(fullpath, arg)
  else:
  print 'find: cannot treat ', fullpath
  上面的函數find可以從scitools模組中擷取。與內建函數os.path.walk相反,我們的find函數以大小寫敏感的字母順序來訪問檔案和目錄。
  我們可以使用find函數來列出所有大於1Mb的檔案:
  def checksize2(fullpath, bigfiles):
  size = os.path.getsize(fullpath)
  if size > 1000000:
  bigfiles.append('%.2fMb %s' % (size/1000000.0, fullpath))
  bigfiles = []
  root = os.environ['HOME']
  find(checksize2, root, bigfiles)
  for fileinfo in bigfiles:
  print fileinfo
  參數arg帶來了巨大的靈活性。我們可以使用它來同時存放輸入資料和產生的資料結構。下一個範例將收集所有大於一定尺寸的帶有規定副檔名的檔案的檔案名稱和大小。輸出的結果按照檔案大小排列。
  bigfiles = {'filelist': [], # 檔案名稱和大小列表
  'extensions': ('.*ps', '.tiff', '.bmp'),
  'size_limit': 1000000, # 1 Mb
  }
  find(checksize3, os.environ['HOME'], bigfiles)
  def checksize3(fullpath, arg):
  treat_file = False
  ext = os.path.splitext(fullpath)[1]
  import fnmatch # Unix的shell風格的萬用字元匹配
  for s in arg['extensions']:
  if fnmatch.fnmatch(ext, s):
  treat_file = True # fullpath帶有正確的副檔名
  size = os.path.getsize(fullpath)
  if treat_file and size > arg['size_limit']:
  size = '%.2fMb' % (size/1000000.0) # 列印
  arg['filelist'].append({'size': size, 'name': fullpath})
  # 按照大小排列檔案
  def filesort(a, b):
  return cmp(float(a['size'][:-2]), float(b['size'][:-2]))
  bigfiles['filelist'].sort(filesort)
  bigfiles['filelist'].reverse()
  for fileinfo in bigfiles['filelist']:
  print fileinfo['name'], fileinfo['size']
  注意為列表排序的函數,bigfiles['filelist']函數中的每個元素就是一個字典,鍵size儲存著一個字串,不過在進行比較之前我們必須將單位Mb(最後兩個字元)去掉,並將其轉換為浮點數。
  八、小結
  對於檔案和目錄的處理,雖然可以通過作業系統命令來完成,但是Python語言為了便於開發人員以編程的方式處理相關工作,提供了許多處理檔案和目錄的內建函數。重要的是,這些函數無論是在Unix、Windows還是Macintosh平台上,它們的使用方式是完全一致的。本文詳細解釋了這些函數的使用方法,其中,我們首先介紹了顯示目錄內容的功能,然後描述如何測試一個檔案名稱對應的是一個標準檔案、目錄還是連結,以及提取檔案大小和日期的方法。之後,我們還將介紹如何刪除檔案和目錄,如何複製和刪除檔案,以及怎樣將一個完整的檔案路徑分解成目錄部分和檔案名稱部分,最後,我們講解目錄的建立,以及如何在分類樹中移動目錄並處理檔案。
  • 聯繫我們

    該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

    如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

    A Free Trial That Lets You Build Big!

    Start building with 50+ products and up to 12 months usage for Elastic Compute Service

    • Sales Support

      1 on 1 presale consultation

    • After-Sales Support

      24/7 Technical Support 6 Free Tickets per Quarter Faster Response

    • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.