使用Python,我试图根据每个给定文本文件中的特定短语重命名目录中的一系列.txt文件。换句话说,更具体地说,我有几百个具有任意名称的文本文件,但每个文件中都有一个独特的短语(类似于No.85-2156)。我想用每个文本文件的给定短语替换任意文件名。这个短语并不总是在同一行上(虽然它没有偏离太多),但它总是以相同的格式,并带有No.前缀。在
我看过了os module,我明白了
可能有用,但我不知道如何将这些函数与文本内操作函数(如linecache)或一般的行读取函数结合起来。在
我想了很多方法来完成这项任务,但似乎最简单、最有效的方法是创建一个循环,在文件中找到唯一的短语,将其分配给一个变量,并在移动到下一个文件之前使用该变量重命名文件。在
这看起来应该很容易,以至于我觉得写这个问题很傻。在过去的几个小时里,我一直在阅读文档并通过StackOverflow进行解析,但似乎没有人以前遇到过这个问题——或者至少他们没有问过他们的问题。在
谁能给我指出正确的方向吗?在
编辑1:当我使用this website创建regex模式时,它创建了大量但似乎可行的代码:
import re
txt='No. 09-1159'
re1='(No)' # Word 1
re2='(\\.)' # Any Single Character 1
re3='( )' # White Space 1
re4='(\\d)' # Any Single Digit 1
re5='(\\d)' # Any Single Digit 2
re6='(-)' # Any Single Character 2
re7='(\\d)' # Any Single Digit 3
re8='(\\d)' # Any Single Digit 4
re9='(\\d)' # Any Single Digit 5
re10='(\\d)' # Any Single Digit 6
rg = re.compile(re1+re2+re3+re4+re5+re6+re7+re8+re9+re10,re.IGNORECASE|re.DOTALL)
m = rg.search(txt)
name = m.group(0)
print name
当我操纵它来适应glob.glob
结构,并使其如下所示:
然后打印出模式的字节位置——表示正则表达式模式是正确的。但是,当我在原始的tname = rg.search(contents)
之后添加nname = tname.group(0)
行,并围绕print函数进行更改以反映更改时,会出现以下错误:AttributeError:“NoneType”对象没有属性“group”。当我试图逐行复制并粘贴@joaquin的代码时,它也出现了同样的错误。我本来打算把这篇文章作为评论贴到@spatz的答案上,但我想包含太多的代码,这似乎是表达“新”问题的更好方法。谢谢你们到目前为止的帮助。在
编辑2:以下是@joaquin答案:
import glob
import os
import re
for fname in glob.glob("/directory/structure/here/*.txt"):
with open(fname) as f:
contents = f.read()
tname = re.search('No\. (\d\d\-\d\d\d\d)', contents)
nname = tname.group(1)
print nname
最后一次编辑:我主要使用编写的代码。所发生的是,有些文件没有regex表达式,所以我假设Python会跳过它们。我真傻。所以我花了三天时间学习写两行代码(我知道教训不止这些)。我还使用了这里推荐的错误捕捉方法。我希望我能检查你们所有人的答案,但我最麻烦的是@Joaquin,所以我把它给了他。这是一次很棒的学习经历。谢谢你们这么慷慨的时间。最终代码如下。在
import os
import re
pat3 = "No\. (\d\d-\d\d)"
ext = '.txt'
mydir = '/directory/files/here'
for arch in os.listdir(mydir):
archpath = os.path.join(mydir, arch)
with open(archpath) as f:
txt = f.read()
s = re.search(pat3, txt)
if s is None:
continue
name = s.group(1)
newpath = os.path.join(mydir, name)
if not os.path.exists(newpath):
os.rename(archpath, newpath + ext)
else:
print '{} already exists, passing'.format(newpath)
我不想给你提供一些你不理解就直接复制粘贴的代码,我想带你来看看解决方案,这样你就可以自己写了,更重要的是,获得足够的知识,下次就可以自己动手了。在
完成您需要的代码由三个主要部分组成:
获取文件名列表
这最好用glob模块实现。此模块允许您指定类似shell的通配符,它将扩展它们。这意味着,为了获得给定目录中
.txt
文件的列表,您需要调用函数glob.iglob("/path/to/directory/*.txt")
,并对其结果进行迭代(for filename in ...:
)。在生成新名称
一旦我们有了文件名,我们需要
open()
它,使用read()
读取它的内容,并将其存储在一个变量中,我们可以在其中搜索所需的内容。看起来像这样:现在我们有了内容,我们需要寻找唯一的短语。这可以使用regular expressions完成。将所需的新文件名存储在变量中,例如
newfilename
。在重命名
既然我们有了旧文件名和新文件名,我们只需要简单地重命名文件,这可以使用
os.rename(filename, newfilename)
完成。在如果要将文件移动到其他目录,请使用
os.rename(filename, os.path.join("/path/to/new/dir", newfilename)
。注意,我们需要os.path.join
在这里使用目录路径和newfilename
为文件构造新路径。在对于失败没有检查或保护(检查是archpath是一个文件,如果newpath已经存在,如果搜索成功,等等…),但是这应该是有效的:
编辑:我测试了正则表达式以展示它的工作原理:
^{pr2}$正则表达式非常简单:
{1>用破折号隔开的字符串{4}表示搜索。 括号用于创建一个可以使用
s.group(1)
恢复的组,该组包含代码号。在这就是你之前和之后得到的结果:
文件文本一个.txt, 两个.txt以及三.txt总是一样的,只是数字改变了:
创建文件的备份,然后尝试如下操作:
相关问题 更多 >
编程相关推荐