fs.rename 的奇怪行为:文件删除 (node.js)
Strange behaviour with fs.rename : file deletion (node.js)
我想编写一个自定义脚本,以递归方式重命名文件名中包含一个点的目录中的所有文件。像 :
mv 'foo.bar.avi' 'foo bar.avi'
它还会将目录名称转换为 'a.b.c/x.y.z.mp4' 变为 'a b c/x y.mp4' 并删除所有下划线 _.
结果删除了这个目录下的所有文件,只留下一些空目录,没有任何通知或错误,让我丢失了大约 300 Gb 的未备份数据。
有实现这一壮举的绝妙代码:
var fs = require('fs');
var path = require('path');
var util = require('util');
var fse = require('fs-extra')
var async = require('async');
var walk = function(dir, done) {
var results = [];
fs.readdir(dir, function(err, list) {
if (err) return done(err);
var pending = list.length;
if (!pending) return done(null, results);
list.forEach(function(file) {
file = path.resolve(dir, file);
fs.stat(file, function(err, stat) {
if (stat && stat.isDirectory()) {
walk(file, function(err, res) {
results = results.concat(res);
if (!--pending) done(null, results);
});
} else {
if (file.indexOf('/.') < 0) {
results.push(file);
}
if (!--pending) done(null, results);
}
});
});
});
};
var rename = function(err, filename) {
if (util.isArray(filename)) {
for (var i = 0; i < filename.length; i++) {
rename(err, filename[i]);
}
return;
}
fs.stat(filename, function(err, stat) {
if (!stat.isDirectory()) {
filename2 = filename.split('.');
var extension = filename2.pop();
filename2 = filename2.join(' ').split('_').join(' ') + '.' + extension;
var directory = filename2.split('/');
directory.pop();
directory = directory.join('/');
async.series([
function (callback) {
fse.mkdirs(directory, function (err) {
callback(err, 'fs.mkdirs');
});
},
function(callback) {
fs.rename(filename, filename2, function (err) {
callback(err, 'fs.rename');
});
}
],
function (err, results) {
if (err) {
console.log(err);
}
console.log('All files have been renamed');
});
}
});
}
walk('/Volumes/My Passport/Movies/', function(err, results) {
rename('', results);
});
来不及了,我已经在哀悼了。
我只是想了解这个 fs.rename 是如何删除文件的。
我不敢相信我做到了。我什至没有生气,这太棒了。我的脚本删除了 300gb 的数据,甚至没有一条关于删除的指令。我接受了我的信仰。
我怀疑 fs.rename 在外部驱动器上有问题。
谢谢。
所以,很遗憾地说,问题是你在声明 filename2
时忘记了 var
。因此,filename2
成为一个全局变量。 fs.rename
每次都得到相同的值。解决方案是将 filename2 声明为 var filename2
或删除 async.series
.
我想编写一个自定义脚本,以递归方式重命名文件名中包含一个点的目录中的所有文件。像 : mv 'foo.bar.avi' 'foo bar.avi'
它还会将目录名称转换为 'a.b.c/x.y.z.mp4' 变为 'a b c/x y.mp4' 并删除所有下划线 _.
结果删除了这个目录下的所有文件,只留下一些空目录,没有任何通知或错误,让我丢失了大约 300 Gb 的未备份数据。
有实现这一壮举的绝妙代码:
var fs = require('fs');
var path = require('path');
var util = require('util');
var fse = require('fs-extra')
var async = require('async');
var walk = function(dir, done) {
var results = [];
fs.readdir(dir, function(err, list) {
if (err) return done(err);
var pending = list.length;
if (!pending) return done(null, results);
list.forEach(function(file) {
file = path.resolve(dir, file);
fs.stat(file, function(err, stat) {
if (stat && stat.isDirectory()) {
walk(file, function(err, res) {
results = results.concat(res);
if (!--pending) done(null, results);
});
} else {
if (file.indexOf('/.') < 0) {
results.push(file);
}
if (!--pending) done(null, results);
}
});
});
});
};
var rename = function(err, filename) {
if (util.isArray(filename)) {
for (var i = 0; i < filename.length; i++) {
rename(err, filename[i]);
}
return;
}
fs.stat(filename, function(err, stat) {
if (!stat.isDirectory()) {
filename2 = filename.split('.');
var extension = filename2.pop();
filename2 = filename2.join(' ').split('_').join(' ') + '.' + extension;
var directory = filename2.split('/');
directory.pop();
directory = directory.join('/');
async.series([
function (callback) {
fse.mkdirs(directory, function (err) {
callback(err, 'fs.mkdirs');
});
},
function(callback) {
fs.rename(filename, filename2, function (err) {
callback(err, 'fs.rename');
});
}
],
function (err, results) {
if (err) {
console.log(err);
}
console.log('All files have been renamed');
});
}
});
}
walk('/Volumes/My Passport/Movies/', function(err, results) {
rename('', results);
});
来不及了,我已经在哀悼了。
我只是想了解这个 fs.rename 是如何删除文件的。
我不敢相信我做到了。我什至没有生气,这太棒了。我的脚本删除了 300gb 的数据,甚至没有一条关于删除的指令。我接受了我的信仰。
我怀疑 fs.rename 在外部驱动器上有问题。
谢谢。
所以,很遗憾地说,问题是你在声明 filename2
时忘记了 var
。因此,filename2
成为一个全局变量。 fs.rename
每次都得到相同的值。解决方案是将 filename2 声明为 var filename2
或删除 async.series
.