os.walk()两次访问同一个文件夹

时间:2017-09-07 00:55:54

标签: python python-3.x os.walk

我正在使用mutagen library编写简单脚本,它会计算文件夹中的音频文件数量和文件夹的整个音频播放时间(包括子文件夹中的音频文件)。

import os,sys
from datetime import datetime,timedelta
from mutagen.mp3 import MP3
from mutagen.flac import FLAC
from mutagen.aac import AAC
from mutagen.aiff import AIFF
from mutagen.asf import ASF

audio_ext={"mp3":lambda x: MP3(x).info.length,
           "aac":lambda x: AAC(x).info.length,
           "wmv":lambda x: ASF(x).info.length,
           "wma":lambda x: ASF(x).info.length,
           "asf":lambda x: ASF(x).info.length,
           "flac":lambda x: FLAC(x).info.length,
           "aiff":lambda x: AIFF(x).info.length,}

def scan_lib(path):
    playtime = 0
    audio_files = 0
    for root,dirs,files in os.walk(path,followlinks=False):
        for f in files:
           try:
               playtime += audio_ext[f[len(f)-f[::-1].index('.'):]](os.path.join(root,f))
               audio_files += 1
           except (KeyError,ValueError):
               pass

        for d in dirs:
            dir_playtime,dir_audios = scan_lib(os.path.join(root,d))
            playtime +=dir_playtime
            audio_files += dir_audios

    print("\nLibrary:",path)
    print("Amount of audio files:",audio_files)
    print("Total playing time:\nDays\tHours\tMin\tSec\n%d\t%d\t%d\t%d\n" % convert_pt(playtime))
    return playtime,audio_files

def convert_pt(sec):
    t = datetime(1,1,1) + timedelta(seconds=int(sec))
    return t.day-1, t.hour,t.minute,t.second

main_path = sys.argv[1]
playtime,audio_files = scan_lib(main_path)

经过一些测试,我发现我的脚本访问了一些文件夹两次。通常这些目录是另一个子文件夹中的子文件夹。结果它打印出这种结果:

$ python3 music_scan.py 

Library: ~/Music/
Amount of audio files: 3520
Total playing time:
Days    Hours   Min Sec
9   7   30  26

但实际上,如果您将所有音轨移动到一个文件夹并在该测试文件夹上运行脚本,则会显示不同的结果:

$ python3 music_scan.py ~/test
Library: ~/test/
Amount of audio files: 885
Total playing time:
Days    Hours   Min Sec
2   15  49  9

测试文件夹中的音轨数量确实是885。我用ls | wc -l命令检查了它 那么为什么os.walk()会访问一些子文件夹两次?

1 个答案:

答案 0 :(得分:4)

os.walk已经递归遍历整个目录树。

然而,您以递归方式调用方法scan_lib

def scan_lib(path):
    ...
    for root,dirs,files in os.walk(path,followlinks=False):
        ...
        for d in dirs:
            dir_playtime,dir_audios = scan_lib(os.path.join(root,d))
            ...

使用os.listdir代替os.walk并保留递归调用,或者只删除以for d in dirs:开头的4行。