1. ホーム
  2. スクリプト・コラム
  3. ルア

フォルダの再帰的削除のためのLuaスクリプト

2022-02-11 16:03:37

コピーコード コードは以下の通りです。

rmdir in quick-cocos2d-x with lua.

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サンプル例では、システムコマンドを使用してフォルダを再帰的に削除するリセットメソッドが用意されています。

コピーコード コードは以下の通りです。

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();
}

しかし、このリセットをiosシミュレーターで実行すると、xcodeは次のようなワーニングを報告します。

iOS Simulator の libSystem が順番を無視して初期化されました。これは、ホストの実行ファイルを実行したり、ホストの dylib を挿入したりすることで発生することが多いようです。

そこで、別の選択肢に目をつけました。

2.純粋なLua

Pure 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の実機はまだテストしていません。テストし次第、更新します。