2011-03-09 49 views
0

背景:我的一个朋友,他可能会有一些强迫症的问题,告诉我一个故事,他如何不打算将他的工作时间用于重命名大量歌曲文件那里有An,The,Of和更多的大写字母。文件重命名;我可以得到一些反馈意见

准则:他给了我一个单词列表,在这里省略,因为你会在代码中看到它们,并告诉我大写字母是O.K.如果他们在歌曲的开头,但是否则他们必须是小写字母。

问题1:这实际上是我的第一个脚本,我正在寻找一些反馈。如果有更好的方法来写这个,我想看看它,所以我可以改进我的编码。该脚本是功能性的,并且正是我想要的。

问题2:最初我没有全部3个功能。我只有取代单词的功能。由于某些原因,它不适用于看起来像这个“月球黑暗面”的文件。当我运行代码时,“Of”将被替换,但“The”将不会被替换。因此,通过试验和错误,我发现如果我小写了文件的第一个字母,那么执行我的替换功能,最后输入大写的文件,它会起作用。任何线索为什么?

import os 
words = ['A','An','The','Of','For','To','By','Or','Is','In','Out','If','Oh','And','On','At'] 
fileList = [] 
rootdir = '' 
#Where are the files? Is the input a valid directory? 
while True: 
    rootdir = raw_input('Where is your itunes library? ') 
    if os.path.isdir(rootdir): break 
    print('That is not a valid directory. Try again.') 
#Get a list of all the files in the directory/sub-directory's 
for root, subFolders, files in os.walk(rootdir): 
    for file in files: 
     fileList.append(os.path.join(root)) 
#Create a function that replaces words. 
def rename(a,b,c): 
    for file in os.listdir(c): 
     if file.find(a): 
      os.rename(file,file.replace(a,b)) 
#Create a function that changes the first letter in a filename to lowercase. 
def renameL(): 
    for file in os.listdir(os.getcwd()): 
     if file.find(' '): 
      os.rename(file,file.replace(file,file[0].lower()+file[1:])) 
#Creat a function that changes the first letter in a filename to uppercase. 
def renameU(): 
    for file in os.listdir(os.getcwd()): 
     if file.find(' '): 
      os.rename(file,file.replace(file,file[0].upper()+file[1:])) 
#Change directory/lowercase the first letter of the filename/replace the offending word/uppercase the first letter of the filename. 
for x in fileList: 
    for y in words:  
     os.chdir(x) 
     renameL()   
     rename(y,y.lower(),x) 
     renameU() 

Exit = raw_input('Press enter to exit.') 
+0

欢迎来到SO。一些笔记。这是精确回答精确问题的地方。所以,背景是不需要的。另外,*请提供反馈/意见*类型的问题更适合http://programmers.stackexchange.com。 – 2011-03-09 07:45:55

+0

感谢您的意见。 – Chris 2011-03-09 08:33:23

回答

0
  1. 使用set,而不是一个列表。 (它更快)
  2. 我不确定你在那里做什么。我采取的方法是小写整个事情,然后大写每个单词的第一个字母,只要该单词不在集合中,然后大写第一个字母(无论它是哪种特殊话)。

C#版本,我写了一会儿前:

private static HashSet<string> _small = new HashSet<string>(new[] { "of", "the", "and", "on", "sur", "de", "des", "le", "la", "les", "par", "et", "en", "aux", "d", "l", "s" }); 
static string TitleCase(string str) 
{ 
    if (string.IsNullOrEmpty(str)) return string.Empty; 
    return string.Concat(char.ToUpper(str[0]), 
     Regex.Replace(str, @"\w+", m => 
      { 
       string lower = m.Value.ToLower(); 
       return _small.Contains(lower) 
        ? lower 
        : string.Concat(char.ToUpper(lower[0]), lower.Substring(1)); 
      }) 
      .Substring(1)); 
} 

我用正则表达式,而不是分裂的空间,因为我有很多的分离,在那里法语单词的替代。

+0

他的代码中有几个列表,我怀疑一个集合通常比列表更快。那么,你能详细说明你的第一点吗? – 2011-03-09 07:46:55

+0

@ Space_C0wb0y:没关系,我没有想到通过。当你在'myset'中做'x'的时候速度会更快,但如果你只是迭代它,它没有什么区别。 – mpen 2011-03-10 01:44:08

1

重复的代码通常被认为是不好的风格(DRY是流行词)。另外我通常不尝试交错功能。

对于这个小脚本的“设计”,我将首先遍历目录并创建一个包含所有音频文件和目录的大型列表。然后我编写一个函数来处理更改列表中的一个项目,并使用map创建另一个列表。现在你有一个current和一个want列表。然后我会zip这些列表一起重新命名。

如果你的音乐库真的很大,你可以使用itertools,所以你在内存中没有大的列表,但是迭代器(一次只能在内存中存储一​​个项目)。这在Python中非常简单:使用imap而不是mapizip而不是zip

为了给你一个印象和一些有用的功能提示,这里是我如何做到这一点的粗略草图。 (警告:未经测试)

import os 
import sys 

words = ['A','An','The','Of','For','To','By','Or','Is','In','Out','If','Oh','And','On','At'] 
wantWords = map(str.lower, words) 

def main(args): 
    rootdir = args[1] 
    files = findFiles(rootdir) 
    wantFiles = map(cleanFilename, files) 
    rename(files, wantFiles) 

def findFiles(rootdir): 
    result = [] 
    for root, subFolders, files in os.walk(rootdir): 
     for filename in files: 
      result.append(os.path.join(root, filename)) 
    return result 

def cleanFilename(filename): 
    # do replacement magic 

def rename(files, wantFiles): 
    for source, target in zip(files, wantFiles): 
     os.rename(source, target) 

if __name__ == '__main__': 
    main(sys.argv) 

的好处是,你可以在main()看什么不看入的功能的细节发生。每个功能都做不同的事情。在只走文件系统时,只改变一个文件名,实际上重命名文件。

+0

感谢您的意见。 – Chris 2011-03-09 08:34:39

1

OK,一些批评:

  • 不要提示为参数,在命令行中得到他们。它使得测试,脚本和其他许多事情变得更加容易。
  • 你得到的实现不会区分,例如“the”from“theatre”
  • 您正在使用current-working-directory传递您正在处理的目录。不要这样做,只是使用一个变量。
  • 别人说:“使用set,速度更快”。那个建议是不正确的;正确的建议是“使用set,因为你需要一套”。一组是独特项目的无序集合(一个列表是不必要唯一项目的有序集合)。作为使用正确集合的奖励,您的程序可能运行得更快。
  • 你需要正确地分配你想要做的工作。我会解释一下:

你的程序有两个部分:1.你需要遍历某个目录中的所有文件,并根据一些规则重命名它们。 2.规则给定一个字符串(是的,这将是一个文件名,但忘记了这一点),大写第一个单词和所有后面的单词不在某些给定的集合。你有(1)下来很好拍,所以深入挖掘(2)。步骤是一个。把所有东西都敲成小写。湾将字符串分解成单词。 C。对于每个单词,如果你应该这样做,就把它大写。 d。将单词加入字符串。

写(2),并编写调用它,确保它正常工作的测试程序:

assert capitalizeSongName('the Phantom Of tHe OPERA') == 'The Phantom of the Opera' 

当你快乐(2),写(1)整个事情应该工作。

+0

我很欣赏这些输入,并会尝试弄清楚如何实施您的建议。 – Chris 2011-03-09 08:35:45