在lua中递归删除一个文件夹

原文:http://zengrong.net/post/2129.htm

在使用 quick-cocos2d-x 做项目热更新的时候,我需要建立临时文件夹以保存下载的更新包。在更新完成后,我需要删除这些临时文件和文件夹。
cocos2d-x 和 quick-cocos2d-x 都没有提供删除文件夹功能。我做了如下2个尝试:

  1. 使用C++
    在 cocos2d-x 2.x 中的 https://github.com/cocos2d/cocos2d-x/tree/v2/extensions/AssetsManage 包中提供了一个 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 的 https://github.com/cocos2d/cocos2d-x/tree/v2/samples/Cpp/AssetsManagerTest 范例中提供了一个 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 其实是个噱头。这里还是要依赖 https://github.com/keplerproject/luafilesystem,好在 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 真机还没有测试。我测试后会立即更新。

我使用的第二种方式 感谢分享 :2:

这么快就发上来了。

感谢分享 顶一个

热更新的那个文章还在写,这只是其中的一个副产品。

您的文章已被推荐到CocoaChina首页热门文章精选,感谢您的分享。

:2:Good:2:

感谢分享 顶一个

多谢分享!

多谢分享!

加精华就上Cocos引擎中文官网首页了!http://cn.cocos2d-x.org/

楼主加油!

回复支持一下。

os.execute(“rm -rf xxx”)

多谢分享!:2::2::2:

system(command.c_str()); 在真机上不成功~

这么好的文章,怎么能不Mark呢!!是吧!!!:2::2::2::2::2:

其实没必要这么麻烦
用C++写 跨平台代码就行了

我的实现
/*

  • Remove all file in a direcotry is platform depended.
    /
    bool AssetsManager::removeAllFilesInDirectory(const char path)
    {
    if (!path)
    {
    return false;
    }
    #if (CC_TARGET_PLATFORM != CC_PLATFORM_IOS)
    size_t len = strlen(path);
    char cmd={0};
    #if (CC_TARGET_PLATFORM != CC_PLATFORM_WIN32)
    len += strlen("rm -rf ");
    snprintf(cmd,len+3,"rm -rf %s/
    ",path);
    #else
    len += strlen("del /q /s ");
    snprintf(cmd,len+3,"del /q /s %s\
    ",path);
    #endif
    int res = system(cmd);
    if(res == -1)
    {
    return false;
    }
    return true;
    #else
    return rmDir_IOS(path);
    #endif
    }

rmDir_IOS 这个函数是我用unix函数 封了一个简单的递归删除文件夹的API

请问在cocos2dx下如何用纯lua呢?好像cocos2dx没有包含lfs

感谢分享:14: