> For the complete documentation index, see [llms.txt](https://wiki.redmodding.org/scripting-cyberpunk/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://wiki.redmodding.org/scripting-cyberpunk/cyber-engine-tweaks/cet-functions/utilities/files.md).

# Files

## File Exists

#### Definition

```swift
fileExists(path: string) -> boolean
```

#### Usage example

```lua
print(fileExists('my_file.lua'))
-- true
```

#### Source code

```lua
function fileExists(path)
    local f = io.open(path, 'r')
    return f ~= nil and io.close(f)
end
```

## Get Files Recursively

#### Definition

```swift
getFilesRecursive(path: string, maxDepth: integer) -> table
```

```lua
--
-- getFilesRecursive()
--
-- @param  string    path      The starting path: Default: '.' (mod's root folder)
-- @param  integer   maxDepth  The maximum depth allowed. Default: -1 (unlimited)
--
getFilesRecursive('.', -1)
```

#### Usage example

```lua
local files = getFilesRecursive('.', 2)
```

```
files = {
    "./includes/module-1.lua",
    "./includes/module-2.lua",
    "./includes/sub-folder/sub-module-1.lua",
    "./init.lua",
}
```

#### Source code

```lua
function getFilesRecursive(path, maxDepth, depth, storage)

    -- vars
    path = path or '.'
    maxDepth = maxDepth or -1
    depth = depth or 0
    storage = storage or {}

    -- validate maxDepth
    if maxDepth ~= -1 and depth > maxDepth then
        return storage
    end

    -- sanitize path leading "."
    if not string.find(path, '^%.') then
        path = '.' .. path
    end

    -- sanitize path leading double "//"
    if string.find(path, '^%.//') then
        path = string.gsub(path, '^%.//', './')
    end

    -- get dir/files
    local files = dir(path)

    -- validate files
    if not files or (type(files) == 'table' and #files == 0) then
        return storage
    end

    -- loop files
    for _, file in ipairs(files) do

        -- directory
        if file.type == 'directory' then
            getFilesRecursive(path .. '/' .. file.name, maxDepth, depth + 1, storage)

        -- lua file
        elseif string.find(file.name, '%.lua$') then
            table.insert(storage, path .. '/' .. file.name)
        end

    end

    return storage

end
```

## Get Folders Recursively

#### Definition

```swift
getFoldersRecursive(path: string, maxDepth: int) -> table
```

```lua
--
-- getFoldersRecursive()
--
-- @param  string    path      The starting path: Default: '.' (mod's root folder)
-- @param  integer   maxDepth  The maximum depth allowed. Default: -1 (unlimited)
--
getFoldersRecursive('.', -1)
```

#### Usage example

```lua
local folders = getFoldersRecursive('.', 2)
```

<pre><code><strong>folders = {
</strong>    "./includes",
    "./includes/sub-folder",
}
</code></pre>

#### Source code

```lua
function getFoldersRecursive(path, maxDepth, depth, storage)

    -- vars
    path = path or '.'
    maxDepth = maxDepth or -1
    depth = depth or 0
    storage = storage or {}

    -- validate maxDepth
    if maxDepth ~= -1 and depth > maxDepth then
        return storage
    end

    -- sanitize path leading "."
    if not string.find(path, '^%.') then
        path = '.' .. path
    end

    -- sanitize path leading double "//"
    if string.find(path, '^%.//') then
        path = string.gsub(path, '^%.//', './')
    end

    -- get dir/files
    local files = dir(path)

    -- validate files
    if not files or (type(files) == 'table' and #files == 0) then
        return storage
    end

    -- loop files
    for _, file in ipairs(files) do

        -- directory
        if file.type == 'directory' then
            table.insert(storage, path .. '/' .. file.name)
            getFoldersRecursive(path .. '/' .. file.name, maxDepth, depth + 1, storage)
        end

    end

    return storage

end
```
