How to get all the files inside a folder?

:information_source: Attention Topic was automatically imported from the old Question2Answer platform.
:bust_in_silhouette: Asked By mateusak
:warning: Old Version Published before Godot 3 was released.

Indeed.

:bust_in_silhouette: Reply From: volzhs
func list_files_in_directory(path):
	var files = []
	var dir = Directory.new()
	dir.open(path)
	dir.list_dir_begin()

	while true:
		var file = dir.get_next()
		if file == "":
			break
		elif not file.begins_with("."):
			files.append(file)

	dir.list_dir_end()

	return files

I know this is an old question, but could you maybe provide some explanation to how this works, as that would be a lot more helpful than just a code to copy and paste.

Sigma-One | 2017-08-18 17:42

func list_files_in_directory(path):
    var files = []
    var dir = Directory.new()
    dir.open(path)
    dir.list_dir_begin()

Create an array called “files”, create a new Directory called “dir”, you give to “dir” the path of the folder to open, probably something like “res://scenes”, and you start to look for filenames with list_dir_begin()

while true:
    var file = dir.get_next()
    if file == "":
        break
    elif not file.begins_with("."):
        files.append(file)

You get the next filename until you get to the end of the stream with (if file == “”), you go out of the loop with “break”, elif (else if) the file does not start with a “.” means the current file is not a directory (You can use file.current_is_dir ( ) wich return true or false) you push the value in the end of the array files (to keep a track, no need to reopen a Directory after that, and in this case the author don’t want the subpaths, just filenames)

dir.list_dir_end()

Close de stream of data (not needed in this case according to the godot doc)

return files

And this is not just a code to copy paste, but a code to understand, line by line, it is speaking for itself, usually you just have to read the godot doc to find what the different classes and functions are doing

Jackain | 2018-01-13 18:04

I get ERR_PARSE_ERROR with “dir.open(“res://whatever”)”

Aaron Franke | 2019-01-16 12:01

According to the documentation here, you no longer need to call list_dir_end() after get_next() returns the empty string, since it is called automatically.

Diet Estus | 2019-01-23 03:21

At least as of Godot 3.1 Directory.list_dir_begin() takes in two optional parameters: skip_navigational and skip_hidden. If skip_navigational is true then “.” and “…” (the current and parent directories, respectively) will be ignored and if skip_hidden is true then whatever the OS considers a hidden file (file name starts with “.” on *NIXes) will be ignored.

They both default to false, but setting them both to true would eliminate the need for the elif not file.begins_with("."): check in this example.

Hammer Bro. | 2019-09-01 16:02

:bust_in_silhouette: Reply From: anachronost

As I didn’t find a complete solution that goes through the subdirectories while searching and writing this and came here, here goes:

Below is a complete solution for recursively getting all files and folders under a root folder.

Return all filenames and directories (with full filepaths) under root path.

func get_dir_contents(rootPath: String) -> Array:
	var files = []
	var directories = []
	var dir = Directory.new()

	if dir.open(rootPath) == OK:
		dir.list_dir_begin(true, false)
		_add_dir_contents(dir, files, directories)
	else:
		push_error("An error occurred when trying to access the path.")

	return [files, directories]

Recursively list and add all filenames and directories with full paths to their respective arrays.



func _add_dir_contents(dir: Directory, files: Array, directories: Array):
	var file_name = dir.get_next()

	while (file_name != ""):
		var path = dir.get_current_dir() + "/" + file_name

		if dir.current_is_dir():
			print("Found directory: %s" % path)
			var subDir = Directory.new()
			subDir.open(path)
			subDir.list_dir_begin(true, false)
			directories.append(path)
			_add_dir_contents(subDir, files, directories)
		else:
			print("Found file: %s" % path)
			files.append(path)

		file_name = dir.get_next()

	dir.list_dir_end()
:bust_in_silhouette: Reply From: Poobslag

In trying to solve this problem myself, I wrote a function which traverses a directory to find all PNG assets.

"""
Returns a list of all png files in the /assets directory.

Recursively traverses the assets directory searching for pngs. Any additional directories it discovers are appended to
a queue for later traversal.

Note: We search for '.png.import' files instead of searching for png files directly. This is because png files
  disappear when the project is exported.
"""
func _find_png_paths() -> Array:
  var png_paths := [] # accumulated png paths to return
  var dir_queue := ["res://assets"] # directories remaining to be traversed
  var dir: Directory # current directory being traversed
  
  var file: String # current file being examined
  while file or not dir_queue.empty():
    # continue looping until there are no files or directories left
    if file:
      # there is another file in this directory
      if dir.current_is_dir():
        # found a directory, append it to the queue.
        dir_queue.append("%s/%s" % [dir.get_current_dir(), file])
      elif file.ends_with(".png.import"):
        # found a .png.import file, append its corresponding png to our results
        png_paths.append("%s/%s" % [dir.get_current_dir(), file.get_basename()])
    else:
      # there are no more files in this directory
      if dir:
        # close the current directory
        dir.list_dir_end()
      
      if dir_queue.empty():
        # there are no more directories. terminate the loop
        break
      
      # there are more directories. open the next directory
      dir = Directory.new()
      dir.open(dir_queue.pop_front())
      dir.list_dir_begin(true, true)
    file = dir.get_next()
  
  return png_paths
:bust_in_silhouette: Reply From: ST4153

some optimizations to volzhs answer

func get_files(path):
	var files = []
	var dir = Directory.new()
	dir.open(path)
	dir.list_dir_begin(true)

	var file = dir.get_next()
	while file != '':
		files += [file]
		file = dir.get_next()

	return files
:bust_in_silhouette: Reply From: MintSoda

A slightly cleaner version for recursively getting files inside a directory. (Godot 3)

static func get_dir_files(path: String) -> PoolStringArray:
	var arr: PoolStringArray
	var dir := Directory.new()
	dir.open(path)

	if dir.file_exists(path):
		arr.append(path)

	else:
		dir.list_dir_begin(true,  true)
		while(true):
			var subpath := dir.get_next()
			if subpath.empty():
				break
			arr += get_dir_files(path.plus_file(subpath))

	return arr

Sorry but this one’s slow in speed tests compared to anachronost’s answer which is about 22 times faster (that one’s recursive too).

rainlizard | 2021-03-30 04:07

:bust_in_silhouette: Reply From: Jair0
func get_files_recursively(path : String, type = []) -> PoolStringArray:
    var files : PoolStringArray = []
    var dir = Directory.new()
    assert( dir.open(path) == OK )
    assert( dir.list_dir_begin(true, true) == OK )
            
    var next = dir.get_next()
    while !next.empty():
            if dir.current_is_dir():
                files += get_files_recursively("%s/%s" % [dir.get_current_dir(), next], type)
            else:
                if type.empty() or next.rsplit(".", true, 1)[1] in type:
                    files.append("%s/%s" % [dir.get_current_dir(), next])
            next = dir.get_next()
    
    dir.list_dir_end()
    return files
:bust_in_silhouette: Reply From: TheYellowArchitect

For Godot 4, all answers below work with DirAccess instead of Directory