I have the following directory structure:
-mailDir
-folderA
-sub1
-sub2
-inbox
-1.txt
-2.txt
-89.txt
-subInbox
-subInbox2
-folderB
-sub1
-sub2
-inbox
-1.txt
-2.txt
-200.txt
-577.txt
目标是将收件箱文件夹下的所有txt文件复制到另一个文件夹中。 为此,我尝试了以下代码
import os
from os import path
import shutil
rootDir = "mailDir"
destDir = "destFolder"
eachInboxFolderPath = []
for root, dirs, files in os.walk(rootDir):
for dirName in dirs:
if(dirName=="inbox"):
eachInboxFolderPath.append(root+"\\"+dirName)
for ii in eachInboxFolderPath:
for i in os.listdir(ii):
shutil.copy(path.join(ii,i),destDir)
如果收件箱目录仅包含.txt文件,则上述代码可以正常工作。由于folderA目录下的inbox文件夹具有其他子目录以及.txt文件,因此代码返回权限被拒绝错误。我了解的是shutil.copy不允许复制文件夹。
目标是仅将每个收件箱文件夹中的txt文件复制到其他位置。如果不同收件箱文件夹中的文件名相同,则必须保留两个文件名。在这种情况下,我们如何改进代码?请注意,除.txt以外,其他所有文件夹均仅是文件夹。
答案 0 :(得分:2)
一个简单的解决方案是使用字符串endswith()
方法来过滤所有不具有i
扩展名的.txt
。
import os
from os import path
import shutil
rootDir = "mailDir"
destDir = "destFolder"
eachInboxFolderPath = []
for root, dirs, files in os.walk(rootDir):
for dirName in dirs:
if(dirName=="inbox"):
eachInboxFolderPath.append(root+"\\"+dirName)
for ii in eachInboxFolderPath:
for i in os.listdir(ii):
if i.endswith('.txt'):
shutil.copy(path.join(ii,i),destDir)
这应该忽略用os.listdir(ii)
找到的所有文件夹和非txt文件。我相信这就是您想要的。
答案 1 :(得分:0)
只记得我曾经写过几个文件来解决这个确切的问题。您可以找到源代码here on my Github。
简而言之,这里有两个有趣的功能:
list_files(loc, return_dirs=False, return_files=True, recursive=False, valid_exts=None)
copy_files(loc, dest, rename=False)
根据您的情况,您可以将以下函数复制并粘贴到您的项目中,然后像这样修改copy_files
:
def copy_files(loc, dest, rename=False):
# get files with full path
files = list_files(loc, return_dirs=False, return_files=True, recursive=True, valid_exts=('.txt',))
# copy files in list to dest
for i, this_file in enumerate(files):
# change name if renaming
if rename:
# replace slashes with hyphens to preserve unique name
out_file = sub(r'^./', '', this_file)
out_file = sub(r'\\|/', '-', out_file)
out_file = join(dest, out_file)
copy(this_file, out_file)
files[i] = out_file
else:
copy(this_file, dest)
return files
然后这样称呼它:
copy_files('mailDir', 'destFolder', rename=True)
重命名方案可能不完全是您想要的方案,但至少不会覆盖您的文件。我相信这应该可以解决您所有的问题。
答案 2 :(得分:0)
您在这里:
import os
from os import path
import shutil
destDir = '<absolute-path>'
for root, dirs, files in os.walk(os.getcwd()):
# Filter out only '.txt' files.
files = [f for f in files if f.endswith('.txt')]
# Filter out only 'inbox' directory.
dirs[:] = [d for d in dirs if d == 'inbox']
for f in files:
p = path.join(root, f)
# print p
shutil.copy(p, destDir)
快速而简单。
对不起,我忘记了此处的内容,您也需要唯一的文件名。上述解决方案仅适用于单个收件箱文件夹中的不同文件名。
要从多个收件箱复制文件并在目标文件夹中使用唯一的名称,可以尝试以下操作:
import os
from os import path
import shutil
sourceDir = os.getcwd()
fixedLength = len(sourceDir)
destDir = '<absolute-path>'
filteredFiles = []
for root, dirs, files in os.walk(sourceDir):
# Filter out only '.txt' files in all the inbox directories.
if root.endswith('inbox'):
# here I am joining the file name to the full path while filtering txt files
files = [path.join(root, f) for f in files if f.endswith('.txt')]
# add the filtered files to the main list
filteredFiles.extend(files)
# making a tuple of file path and file name
filteredFiles = [(f, f[fixedLength+1:].replace('/', '-')) for f in filteredFiles]
for (f, n) in filteredFiles:
print 'copying file...', f
# copying from the path to the dest directory with specific name
shutil.copy(f, path.join(destDir, n))
print 'copied', str(len(filteredFiles)), 'files to', destDir
如果您需要复制所有文件而不是仅复制txt文件,则只需在过滤掉文件的同时将条件f.endswith('.txt')
更改为os.path.isfile(f)
。