我有一个函数,我想枚举目标文件夹中的所有文件和文件夹。当/如果它找到rar文件我希望它提取它们然后删除它们。对于多部分存档,它还将检查并删除剩余文件(已经使用第一卷提取的文件)。
我在for循环中使用os.listdir,但这种方法的问题是: a)我不认为它会处理子文件夹而不为它们编写递归循环(我不想这样做,因为递归会伤害我的头脑)。 b)因为for循环只在开头创建了它的字典(?),当它循环到一个在前一次迭代中已被删除的文件名时,我将无法找到该文件。
看来os.walk对于上面的“a)”可能更好,到目前为止我的研究表明我应该能够在每次迭代时实时更新os.walk。但是我无法弄清楚如何做到这一点。
我有这样的事情:
for root, dirs, files in os.walk('d:\\test'):
for file in files:
print 'files (before remove): ', file, files
# This is where I would do some operation that deletes one or more files.
files.remove(file)
print 'files (after remove): ', file, files
然而输出是这样的:
D:\test>d:\Python27\python.exe d:\file.py
files (before remove): Crystal.part01.rar ['Crystal.part01.rar', 'Crystal.part02.rar', 'Crystal.part03.rar', 'Crystal.part04.rar', 'Crystal.part05.rar', 'Crystal.part06.rar']
files (after remove): Crystal.part01.rar ['Crystal.part02.rar', 'Crystal.part03.rar', 'Crystal.part04.rar', 'Crystal.part05.rar', 'Crystal.part06.rar']
files (before remove): Crystal.part03.rar ['Crystal.part02.rar', 'Crystal.part03.rar', 'Crystal.part04.rar', 'Crystal.part05.rar', 'Crystal.part06.rar']
files (after remove): Crystal.part03.rar ['Crystal.part02.rar', 'Crystal.part04.rar', 'Crystal.part05.rar', 'Crystal.part06.rar']
files (before remove): Crystal.part05.rar ['Crystal.part02.rar', 'Crystal.part04.rar', 'Crystal.part05.rar', 'Crystal.part06.rar']
files (after remove): Crystal.part05.rar ['Crystal.part02.rar', 'Crystal.part04.rar', 'Crystal.part06.rar']
我认为这是有道理的......我们可以看到列表得到更新,但是因为我已经陷入了(第二个)For语句,它创建了一个文件列表,它继续尝试循环遍历原始列表现在偏移一个的顺序,创建一个“跳过”效果。
如何让目录中的每个文件都可以运行,除非让调用循环知道跳过已被删除的项目?
更新 - 假设可以这样做,我可能不正确。是什么给了我这个想法是从python文档剪下来的:
当topdown为
True
时,调用者可以就地修改dirnames列表 (可能使用del
或切片分配),而walk()
只会递归 进入名称保留在dirnames中的子目录;这可以 用来修剪搜索,强加一个特定的访问顺序,甚至 通知walk()
有关调用者创建或重命名的目录 在它再次恢复walk()
之前。自上而下修改dirnamesFalse
对步行的行为没有影响,因为在自下而上 模式dirnames中的目录是在dirpath本身之前生成的 是生成的。
再次阅读它我看到它只提到了dirnames而不是文件名 - 所以虽然我仍然不明白完成这个的确切方法,但看起来你可能只能操作dirnames到位了。
答案 0 :(得分:0)
sendAjax = () => {
//this.props.navigation returns a value and I can navigate to 'Login'
if(!Regex.test(this.state.email)){
}else if(this.state.password != this.state.confirmPwd){
Alert.alert("The passwords don't match!");
}else{
const fn = encodeURIComponent(this.state.firstname);
...
const hashDigest = sha256(p);
const requestBody = `firstname=${fn}...
//POST
fetch("http://localhost:3000/users", {
method: "POST",
mode: "cors",
headers: {
"Content-Type": "application/x-www-form-urlencoded"
},
body: requestBody
}).then(function (res, next) {
console.log("fetch request ", JSON.stringify(res.ok));
if(res.ok){
res.json().then(function (json) {
if(json.registerstate){
Alert.alert('Register success, please login');
//Cannot read property 'navigation' of undefined
this.props.navigation.navigate('Login')
}
});
}
})
.then((res) => {
Alert.alert("then working");
})
....
}
}
正如您所发现的那样, for root, dirs, files in os.walk('d:\\test'):
for file in files:
#process stuff
是您正在迭代的列表 - you should not modify it。当您files
删除在for循环迭代中未到达的文件时,您可以做三件事(我能想到)
在处理之前检查文件是否存在
process stuff
使用try / except来捕获IOError。如果您想进一步限制异常处理,可以查询错误文本"没有这样的文件或目录:' yourfilehere'"在except套件中,如果异常不同,则重新引发异常。
if fname not in os.listdir(os.getcwd()):
continue
我猜你可以保留一个单独的列表/集合,其中包含你的进程已删除的所有文件,并在尝试处理之前检查文件是否在其中。
如果你真的需要,你可以写一个具有你需要的行为的课程。
fname = 'foo.bar'
try:
with open(fname) as f:
pass
except IOError as e:
#print(e, str(e), repr(e))
if 'No such file' in str(e):
pass
else:
raise
结果
#Python 2.7 code
import collections
class F(collections.deque):
def __iter__(self):
return self
def next(self):
try:
return self.pop()
except IndexError:
raise StopIteration
a = [1,2,3,4]
f = F(a)
for n in f:
print n
if n == 3:
f.remove(2)