迭代excel文件并在Python中的一个文件夹中输出

迭代excel文件并在Python中的一个文件夹中输出,python,operating-system,Python,Operating System,我的文件夹和子文件夹结构如下: D:/src ├─ xyz.xlsx ├─ dist │ ├─ xyz.xlsx │ ├─ xxx.zip │ └─ xxy.xlsx ├─ lib │ ├─ xy.rar │ └─ xyx.xlsx ├─ test │ ├─ xyy.xlsx │ ├─ x.xls │ └─ xyz.xlsx 我想从源目录和子目录中提取所有excel文件(xls或xlsx),根据excel文件名删除副本,并将所有唯一的文件放在D:/dst目录中。如何在Pytho

我的文件夹和子文件夹结构如下:

D:/src
├─ xyz.xlsx
├─ dist
│  ├─ xyz.xlsx
│  ├─ xxx.zip
│  └─ xxy.xlsx
├─ lib
│  ├─ xy.rar
│  └─ xyx.xlsx
├─ test
│  ├─ xyy.xlsx
│  ├─ x.xls
│  └─ xyz.xlsx
我想从源目录和子目录中提取所有excel文件(xls或xlsx),根据excel文件名删除副本,并将所有唯一的文件放在D:/dst目录中。如何在Python中生成以下结果?谢谢 预期结果:

D:/dst
├─ xyz.xlsx
├─ xxy.xlsx
├─ xyx.xlsx
├─ xyy.xlsx
├─ x.xls
以下是我尝试过的:

import os

for root, dirs, files in os.walk(src, topdown=False):
    for file in files:
        if file.endswith('.xlsx') or file.endswith('.xls'):
            #print(os.path.join(root, file))
            try:
                df0 = pd.read_excel(os.path.join(root, file))
                #print(df0)
            except:
                continue
            df1 = pd.DataFrame(columns = [columns_selected])
            df1 = df1.append(df0, ignore_index = True)
            print(df1)
            df1.to_excel('test.xlsx', index = False)

由于您已经拥有了
glob.glob
,因此不需要同时执行
os.walk
,反之亦然。但是,由于glob一次只匹配一个模式,并且无法在扩展中表示可选的额外“x”,因此您需要使用
glob
循环两次,每次扩展一次;或者使用
glob.glob('D:\\src\\\*.xls*)
,它可以匹配
“*.xlsm”
,等等

对于每个匹配的文件,请使用:

使用
os.walk
,您可以在同一个循环中执行每个扩展检查:

for root, dirs, files in os.walk('D:\\src'):
    for file in files:
        if fnmatch.fnmatch(file, '*.xls') or fnmatch.fnmatch(file, '*.xlsx'):
            shutil.move(f'{root}\\{file}', f'D:\\dst\\{file}')
            # shutil.move(root + '\\' + file, 'D:\\dst\\' + file)

由于您已经拥有了
glob.glob
,因此不需要同时执行
os.walk
,反之亦然。但是,由于glob一次只匹配一个模式,并且无法在扩展中表示可选的额外“x”,因此您需要使用
glob
循环两次,每次扩展一次;或者使用
glob.glob('D:\\src\\\*.xls*)
,它可以匹配
“*.xlsm”
,等等

对于每个匹配的文件,请使用:

使用
os.walk
,您可以在同一个循环中执行每个扩展检查:

for root, dirs, files in os.walk('D:\\src'):
    for file in files:
        if fnmatch.fnmatch(file, '*.xls') or fnmatch.fnmatch(file, '*.xlsx'):
            shutil.move(f'{root}\\{file}', f'D:\\dst\\{file}')
            # shutil.move(root + '\\' + file, 'D:\\dst\\' + file)

我想这会满足你的要求:

import os
import shutil


src = os.path.abspath(r'.\_src')
dst = os.path.abspath(r'.\_dst')
wanted = {'.xls', '.xlsx'}

copied = set()

for root, dirs, filenames in os.walk(src, topdown=False):
    for filename in filenames:
        ext = os.path.splitext(filename)[1]
        if ext in wanted and filename not in copied:
            src_filepath = os.path.join(root, filename)
            shutil.copy(src_filepath, dst)
            copied.add(filename)

我想这会满足你的要求:

import os
import shutil


src = os.path.abspath(r'.\_src')
dst = os.path.abspath(r'.\_dst')
wanted = {'.xls', '.xlsx'}

copied = set()

for root, dirs, filenames in os.walk(src, topdown=False):
    for filename in filenames:
        ext = os.path.splitext(filename)[1]
        if ext in wanted and filename not in copied:
            src_filepath = os.path.join(root, filename)
            shutil.copy(src_filepath, dst)
            copied.add(filename)


我想您可以通过
shutil.copytree()
完成所有这些。请看问题。@ahbon,解决这个问题有什么问题吗?谢谢你的提问。我明天会试试,如果我有问题,我会告诉你。@martineau你提到的解决方案将所有xlsx和xls文件复制到一个新文件夹D:/dst,但它保留原始子目录。如果我只是想把它们放在一个文件夹中,而忽略它原来的子目录呢?虽然你添加的pandas dataframe内容有些分散注意力,与你的问题并不完全相关,但它已经暴露了——我认为这就是所谓的,因为它揭示了你为什么要复制这个文件。如果我理解正确,那么确实没有必要先将所有文件复制到单个文件夹,只需使用查找要复制的文件的过程,而不是驱动要执行的文件的串联。这将大大减少需要完成的I/O。我认为您可以通过
shutil.copytree()
来完成所有这些。请看问题。@ahbon,解决这个问题有什么问题吗?谢谢你的提问。我明天会试试,如果我有问题,我会告诉你。@martineau你提到的解决方案将所有xlsx和xls文件复制到一个新文件夹D:/dst,但它保留原始子目录。如果我只是想把它们放在一个文件夹中,而忽略它原来的子目录呢?虽然你添加的pandas dataframe内容有些分散注意力,与你的问题并不完全相关,但它已经暴露了——我认为这就是所谓的,因为它揭示了你为什么要复制这个文件。如果我理解正确,那么确实没有必要先将所有文件复制到单个文件夹,只需使用查找要复制的文件的过程,而不是驱动要执行的文件的串联。这将大大减少需要完成的I/O。为什么要费心调用
os.walk()
,然后在第一次迭代后退出呢?我认为这个问题不清楚,已经要求OP澄清。谢谢@aneroid。我认为shutil.copy在不改变原始数据的情况下会更好,你认为呢?谢谢你的帮助。您的解决方案仅将D:/src-xyz.xlsx复制到D:/dst,而不是从其子文件夹中复制excel文件。@martineau我从OP的代码中收集到他/她希望在第一个文件夹/迭代后停止的代码。即使使用glob,每个扩展也需要两个循环,并且没有
recursive=True
。所以我认为
os.walk()
可以简化这一点。无论如何,在OP的帖子中,他们确实想进行细分。@ahbon是的,如果您希望原始数据保留在
'D:\src'
中,可以使用
复制
而不是
移动
。我删除了
中断
,这样循环在第一次迭代后不会停止。从您的代码来看,您似乎只想使用顶层。此外,如果要递归复制,则需要修改
f'D:\\dst\\{file}
以获得每个文件的父文件夹。否则,它将复制平面,而不复制子曲面。看看这个。为什么要费心调用
os.walk()
只在第一次迭代后退出呢?我认为这个问题不清楚,已经要求OP澄清。谢谢@aneroid。我认为shutil.copy在不改变原始数据的情况下会更好,你认为呢?谢谢你的帮助。您的解决方案仅将D:/src-xyz.xlsx复制到D:/dst,而不是从其子文件夹中复制excel文件。@martineau我从OP的代码中收集到他/她希望在第一个文件夹/迭代后停止的代码。即使使用glob,每个扩展也需要两个循环,并且没有
recursive=True
。所以我认为
os.walk()
可以简化这一点。无论如何,在OP的帖子中,他们确实想进行细分。@ahbon是的,如果您希望原始数据保留在
'D:\src'
中,可以使用
复制
而不是
移动
。我删除了
中断
,这样循环在第一次迭代后不会停止。从您的代码来看,您似乎只想使用顶层。此外,如果要递归复制,则需要修改
f'D:\\dst\\{file}
以获得每个文件的父文件夹。否则,它将复制平面,而不复制子曲面。你的解决方案完美地解决了我将excel文件复制到一个文件夹的问题。阿邦:很高兴听到你这么说,不客气。很抱歉,我的
shutil.copytree()
建议可能导致您分心。当它能