文件扩展名Python

时间:2016-03-23 13:47:23

标签: python

如果一个目录同时包含'.m'和'.xml'文件,我希望脚本同时找到它们(目前它不会这样做,而是转到'else'语句)。给定的参数应该查找目录中的所有文件。

python script.py --dir C:\\path\\path\\*.* #This should take all files (doesn't matter what type ex 'm', 'xml' 'txt' etc.).

如果用户只想要xml文件,他会为'.m'文件写* .xml,反之亦然。请注意,如果用户只想要“XML”或“m”文件,脚本会找到它

def main(argv):
    args = argumentParser(argv)
    if args.dirname.endswith('.m'):
        overrideM(args)
    elif args.dirname.endswith('.xml'):
        xmlOverride(args)
    elif args.dirname.endswith(('.m', '.xml')): #Can I do like this?
        #Here I want to run both of my function.
        overrideM()
        xmlOverride()
    else:
        print "Error can't find files"

我的''功能(小部分)

def overrideM(args):
    for fileName in glob.glob(args.dirname):
        print fileName
        with open(fileName, 'r') as searchFile:
            my_files_content = searchFile.read()
        #...rest of my code

我的'XML'功能(小部分)

def xmlOverride(args):
    for fileName in glob.glob(args.dirname):
        print fileName
        with open(fileName, 'r') as searchFile:
            my_files_content = searchFile.read()
        #...rest of my code

3 个答案:

答案 0 :(得分:1)

elif args.dirname.endswith(('.m', '.xml'))无法工作,如果args是必须的字符串,或者你的代码会出错,那么它就不可能有两个不同的扩展名,如果用户需要,你需要得到一个扩展元组选择两者,如:

def main(argv):
    # make argumentParser return a tuple
    args = argumentParser(argv)
    if sorted(args) == ('.m', '.xml'):
        overrideM()
        xmlOverride()

更好的选择是使用一个带有文件扩展名的泛型函数,只是迭代传入扩展名的args:

def main(argv):
    args = argumentParser(argv)
    for ext in args:
        generic_search(ext)

如果您尝试匹配字符串,则无法在字符串上使用args.dirname.endswith(('.m', '.xml')),字符串根本无法在.m.xml中结束。我还将路径作为一个arg和扩展来搜索单独的args,然后你可以单独地为每个arbase或使用带有多个扩展的 str.endswith 使用os.listdir列出文件。

基本理念如下:

from argparse import ArgumentParser
import os

parser = ArgumentParser()
parser.add_argument("path")
parser.add_argument('ext', nargs='*')

args = parser.parse_args()
path = args.path
exts = args.ext

# what your glob is doing
for f in os.listdir(path):
    if f.endswith(tuple(exts)):
        with open(os.path.join(path, f)) as fle:
            print(fle.name)
            # do whatever

如果您允许用户搜索多个文件,那么除非您在每个函数中执行非常具体的操作,否则最好使用endswith并对目录进行一次传递。

如果您还想搜索所有子目录以及路径,也可以将它与glob结合使用:

from argparse import ArgumentParser
import os
from glob import iglob

parser = ArgumentParser()
parser.add_argument("path")
parser.add_argument('ext', nargs='*')

args = parser.parse_args()
path = args.path
exts = args.ext

for f in chain.from_iterable([iglob(path+"/*"), iglob(path+"/**/*")]):
    if f.endswith(tuple(exts)):
        with open(os.path.join(path, f)) as fle:
            print(fle.name)

再次,它将适用于多个文件扩展名,一次通过目录。 glob适用于单个匹配或者可能是一对,但如果你有多个扩展,那么使用listdir和filer与endswith更有意义。

如果你真的想为每个扩展使用不同的逻辑,你可以拉伸扩展并使用dict调用相应的函数映射扩展名到函数:

from argparse import ArgumentParser
import os
from glob import iglob

def xml(f):
    print(f)

def m(f):
    print(f)

def text(f):
   print(f)

mapped = {"m":m, "xml":xml, "text":text}

parser = ArgumentParser()
parser.add_argument("path")
parser.add_argument('ext', nargs='*')

args = parser.parse_args()
path = args.path
exts = args.ext


for f in chain.from_iterable([iglob(path + "/*"), iglob(path + "/**/*")]):
    ext = f.rsplit(".", 1)
    if len(ext) == 2 and ext[1] in mapped:
        mapped[ext[1]](f)

dict查找是 O(1)所以除了简洁之外它还非常有效。

示例输出:

 $ python 3_payg.py  /home/padraic  .xml 
/home/padraic/sitemap.xml
/home/padraic/yacy/build.xml
/home/padraic/graphviz-master/graphviz.appdata.xml

答案 1 :(得分:0)

1)我与MS Windows没有很大的友谊,但无论如何它与UNIX相似,你可能会在命令提示符下显示你想要的命令产品不仅仅是命令。在UNIX中它将看起来:

 python script.py $(ls home/) 

2)第二个问题是你args将是一个字符串,例如:"file.xml, file.m, file.txt",例如此字符串以.txt结尾。因此,您将错过具有所需扩展名的文件。

要使其工作,您必须迭代文件列表。

files = args.split(",")
for file in files:
     main(file)

答案 2 :(得分:0)

至少在Bash中,{:var "I am a var"}通配符由 shell 扩展,而不是正在运行的进程。 *将包含大量文件。在Windows上可能会有所不同。

你可以通过将目录传递给像这样的搜索来更好地控制(我跳过argparse,但是你应该继续使用它)。

sys.argv

并使用glob or iglob来检索文件。

myscript.py c:\a\directory

这个解决方案的缺点是你不会受益于你的shell关于通配符的花哨设施。

修改

在您的情况下,您不需要使用import sys import glob import os import itertools # retreive your directory to expore, from the arguments # just for the example, better use argparse dir = sys.argv[1] # At this point, you might wish to use os.path.abspath & friends # to have a normalized directory, and check its existence with # os.path.exists. # The patterns to search for: patterns = "*.xml", "*.m" # a generator expression yielding things like # "c:\\my\\dir\\*.xml" and "c:\\my\\dir\\*.m" joint_patterns = (os.path.join(dir, pt) for pt in patterns) # Glob the joint patterns into a super-generator: files = itertools.chain.from_iterable( glob.iglob(pt) for pt in joint_patterns ) # Show the result. the '*' is there to evaluate the super generator # or else it'd print something like # "<itertools.chain object at 0x7fd92ac9efd0>" print(*files) 创建超级生成器。您只需检索每个模式的glob迭代器:

chain