脚本专栏 
首页 > 脚本专栏 > 浏览文章

Lua中实现递归删除一个文件夹

(编辑:jimmy 日期: 2024/12/24 浏览:3 次 )

在使用 quick-cocos2d-x 做项目热更新的时候,我需要建立临时文件夹以保存下载的更新包。在更新完成后,我需要删除这些临时文件和文件夹。

cocos2d-x 和 quick-cocos2d-x 都没有提供删除文件夹功能。我做了如下2个尝试:

1. 使用C++

在 cocos2d-x 2.x 中的 AssetsManager 包中提供了一个 CreateDirectory 方法。这个方法可以跨平台支持创建文件夹。在实际项目中运行没有问题。

复制代码 代码如下:
bool AssetsManager::createDirectory(const char *path)
{
#if (CC_TARGET_PLATFORM != CC_PLATFORM_WIN32)
    mode_t processMask = umask(0);
    int ret = mkdir(path, S_IRWXU | S_IRWXG | S_IRWXO);
    umask(processMask);
    if (ret != 0 && (errno != EEXIST))
    {
        return false;
    }

    return true;
#else
    BOOL ret = CreateDirectoryA(path, NULL);
if (!ret && ERROR_ALREADY_EXISTS != GetLastError())
{
return false;
}
    return true;
#endif
}

在 cocos2d-x 2.x 的 AssetsManager sample 范例中提供了一个 reset 方法,这个方法使用系统命令递归删除文件夹。
复制代码 代码如下:
void UpdateLayer::reset(cocos2d::CCObject *pSender)
{
    pProgressLabel->setString(" ");

    // Remove downloaded files
#if (CC_TARGET_PLATFORM != CC_PLATFORM_WIN32)
    string command = "rm -r ";
    // Path may include space.
    command += "\"" + pathToSave + "\"";
    system(command.c_str());
#else
    string command = "rd /s /q ";
    // Path may include space.
    command += "\"" + pathToSave + "\"";
    system(command.c_str());
#endif
    // Delete recorded version codes.
    getAssetsManager()->deleteVersion();

    createDownloadedDir();
}

但是,这个 reset 在 ios 模拟器中运行的时候,xcode会报这样的warinng:

The iOS Simulator libSystem was initialized out of order. This is most often caused by running host executables or inserting host dylibs. In the future, this will cause an abort.

因此,我转而考虑另一个方案。

2. 纯lua

纯 lua 其实是个噱头。这里还是要依赖 lfs(lua file sytem),好在 quick-cocos2d-x 已经包含了这个库。

lfs.rmdir 命令 和 os.remove 命令一样,只能删除空文件夹。因此实现类似 rm -rf 的功能, 必须要递归删除文件夹中所有的文件和子文件夹。

让我们扩展一下 os 包。
复制代码 代码如下:
require("lfs")

function os.exists(path)
    return CCFileUtils:sharedFileUtils():isFileExist(path)
end

function os.mkdir(path)
    if not os.exists(path) then
        return lfs.mkdir(path)
    end
    return true
end

function os.rmdir(path)
    print("os.rmdir:", path)
    if os.exists(path) then
        local function _rmdir(path)
            local iter, dir_obj = lfs.dir(path)
            while true do
                local dir = iter(dir_obj)
                if dir == nil then break end
                if dir ~= "." and dir ~= ".." then
                    local curDir = path..dir
                    local mode = lfs.attributes(curDir, "mode")
                    if mode == "directory" then
                        _rmdir(curDir.."/")
                    elseif mode == "file" then
                        os.remove(curDir)
                    end
                end
            end
            local succ, des = os.remove(path)
            if des then print(des) end
            return succ
        end
        _rmdir(path)
    end
    return true
end

上面的代码在 iOS 模拟器和 Android 真机上测试成功。Windows系统、Mac OSX 以及 iOS 真机还没有测试。我测试后会立即更新。

上一篇:基于 aLi Lua Web Server 的一个简单例子
下一篇:使用nginx+lua实现信息访问量统计
一句话新闻
一文看懂荣耀MagicBook Pro 16
荣耀猎人回归!七大亮点看懂不只是轻薄本,更是游戏本的MagicBook Pro 16.
人们对于笔记本电脑有一个固有印象:要么轻薄但性能一般,要么性能强劲但笨重臃肿。然而,今年荣耀新推出的MagicBook Pro 16刷新了人们的认知——发布会上,荣耀宣布猎人游戏本正式回归,称其继承了荣耀 HUNTER 基因,并自信地为其打出“轻薄本,更是游戏本”的口号。
众所周知,寻求轻薄本的用户普遍更看重便携性、外观造型、静谧性和打字办公等用机体验,而寻求游戏本的用户则普遍更看重硬件配置、性能释放等硬核指标。把两个看似难以相干的产品融合到一起,我们不禁对它产生了强烈的好奇:作为代表荣耀猎人游戏本的跨界新物种,它究竟做了哪些平衡以兼顾不同人群的各类需求呢?