閒來無事,本著學習nodejs的心態寫點小東西,使用nodejs的api實現rm、cp和mv簡單的刪除/複製/移動檔案/資料夾。
rm刪除檔案
其實也很簡單,如果是檔案就直接用fs.unlinkSync刪除,如果是資料夾就遞迴一個個刪除。
const fs = require("fs");
const { join } = require("path");
module.exports = async function deleteFiles(path) {
// 判斷一下路徑是否真實存在
if (!fs.existsSync(path)) {
console.warn(new Error("路徑不存在。"));
return;
}
const file = fs.lstatSync(path);
// 是檔案,直接刪除
if (file.isFile()) {
fs.unlinkSync(path);
return;
}
// 是資料夾,遍歷下面的所有檔案
if (file.isDirectory()) {
const files = await fs.readdirSync(path);
if (files && files.length) {
for (const fileName of files) {
// 因為我之前專案使用的時候不想刪除隱藏檔案,所以在此過濾了.開頭的檔案
if (fileName.startsWith(".")) {
continue;
}
const p = join(path, fileName);
const f = fs.lstatSync(p);
// 是檔案,直接刪除
if (f.isFile()) {
fs.unlinkSync(p);
}
// 是資料夾,遞迴呼叫 deleteFiles
if (f.isDirectory()) {
await deleteFiles(p);
// 資料夾內部檔案刪除完成之後,刪除資料夾
fs.rmdirSync(p);
}
}
}
return;
}
};Ï
cp複製檔案
複製檔案稍微比刪除複製一點,需要判斷oldPath是檔案還是資料夾,newPath是檔案還是資料夾,再對不同的情況來生成可用的路徑。
const fs = require("fs");
const { join, dirname, basename } = require("path");
module.exports = async function copyFiles(oldPath, newPath) {
// 判斷路徑是否存在,有一個不存在則丟擲錯誤
if (!fs.existsSync(oldPath) || !fs.existsSync(newPath)) {
console.warn(new Error("路徑不存在。"));
return;
}
const oldFile = fs.lstatSync(oldPath);
const newFile = fs.lstatSync(newPath);
// 如果 oldPath 是檔案,則直接複製 oldPath
if (oldFile.isFile()) {
// 需要考慮 newPath 是檔案還是目錄
// 如果是檔案路徑,則可以直接使用進行復制
// 如果是目錄路徑,則需要拼接上 oldPath 的檔名
if (newFile.isDirectory()) {
newPath = join(newPath, basename(oldPath));
}
fs.copyFileSync(oldPath, newPath);
return;
}
// 如果 oldPath 是目錄,則 newPath 應該也使目錄
// 若 newPath 目標路徑是檔案,則預設複製到檔案的目錄下
if (newFile.isFile()) {
console.warn(new Error("引數2應為路徑。"));
newPath = dirname(newPath);
}
if (oldFile.isDirectory()) {
const files = await fs.readdirSync(oldPath);
if (files && files.length) {
// 遍歷目錄下的所有檔案,並將 fileName 拼接上目錄路徑
files.forEach(async (fileName) => {
const oPath = join(oldPath, fileName);
const oFile = fs.lstatSync(oPath);
// 如果拼接後的路徑為檔案,則直接複製
if (oFile.isFile()) {
// 當然,新檔案也需要拼接上 fileName
const newFile = join(newPath, fileName);
fs.copyFileSync(oPath, newFile);
}
// 如果是目錄,則遞迴呼叫 moveFiles
if (oFile.isDirectory()) {
const oldDir = join(oldPath, fileName);
const newDir = join(newPath, fileName);
// 需要判斷拼接後的 newDir 是否存在此目錄,如果不存在則建立
if (!fs.existsSync(newDir)) {
await fs.mkdirSync(newDir);
}
moveFiles(oldDir, newDir);
}
});
}
return;
}
};
mv移動檔案
移動檔案可以偷個懶,先呼叫 copyFiles 函式複製檔案,再呼叫 deleteFiles 刪除檔案就是移動了哈哈哈哈。
const copyFiles = require("./copy");
const deleteFiles = require("./delete");
module.exports = async function moveFiles(oldPath, newPath) {
copyFiles(oldPath, newPath).then((res) => {
deleteFiles(oldPath);
});
};
使用yarn命令呼叫
當然,為了更逼真一些,可以再package.json裡面配置一下rm/mv/cp,這樣就更像了。
"scripts": {
"rm": "node ./rm.js",
"mv": "node ./mv.js",
"cp": "node ./cp.js"
}
直接這樣配置肯定是不行的,我們還需要讀取一下命令時的輸入,使用node自帶的process讀取命令傳的引數
// cp.js
const copyFiles = require("./copy");
copyFiles(process.argv[2], process.argv[3]);
// mv.js
const moveFiles = require("./move");
moveFiles(process.argv[2], process.argv[3]);
// rm.js
const deleteFiles= require('./delete')
deleteFiles(process.argv[2])
最後就可以使用yarn rm/cp/mv xxx xxx
的形式像模像樣的使用啦。
# 刪除檔案
yarn rm ./a.js
# 刪除目錄
yarn rm ./a
# 移動單個檔案
yarn mv ./a.js ./b.js
# 第二個引數為目錄時自動取a.js檔名
yarn mv ./a.js ./b
# 移動目錄所有檔案
yarn mv ./a ./b
# 複製檔案
yarn cp ./a/a.js ./b/b.js
# 第二個引數為目錄時自動取a.js檔名
yarn cp ./a/a.js ./b
# 複製目錄所有檔案
yarn cp ./a ./b