Download

Function to get all filenames in a directory

Hi there,

I’m trying to create a movieplayer in UE4 that will play video files from a directory selected by the user.
How do I create a function that takes a path string as input and returns all the filenames as a string array?

I’ve googled it and tried a lot of examples but can’t get it working.

Thanks in advance,
Rick

There’s at least two ways that I can think of…

  1. Use Epic’s “Object Library”](Asynchronous Asset Loading | Unreal Engine Documentation). This is the same class which is used to do the content browser within the editor. You can probably create a quick UMG widget which accepts a path and shows all files of a type within that path. I’m not 100% sure, but this will probably only read in imported UASSET files. I’ve never tried anything else.

  2. You can use the C++ way by using the file and directory functions within <iostream.h>](<iostream> - C++ Reference) and <fstream.h>](<fstream> - C++ Reference). It’s probably not recommended for compatibility purposes, but it can read in any file on the hard drive.

Rama’s Get All Files and Directories Functions for You

**Rama’s Functions For You

Get All Files

Get All Directories**

**Optional Search String or File Extension Filters!

Platform-Agnostic
**

Copy Paste Code For You!

Stick my code below in a C++ function library of yours somewheres!


**Background**

I wrote my own custom code from scratch to get both files and directories during the UE4 Beta program.

I've actually done a lot of low level file-access code in UE4! 

**The very first C++ code of mine that Epic accepted into the Engine** was a platform-agnostic file operations function! 

[Pull Request #27, IPlatformFile::CopyDirectoryTree](https://github.com/EpicGames/UnrealEngine/pull/27/files)!

( can be found in **GenericPlatformFile.cpp** )

Get All Files, Get All Directories

Both of my functions have option to search recursively all subdirectories

And also an optional file extension filter!

I use this code all the time.

I use a functor and a directory iterator

You can use this code to access any directory on your hard-drive

My method is platform-agnostic, using UE4 functions in IPlatformFile.


**Rama's Copyright Notice**

Please simply include the fact that I am the author of this code if you choose to use it in your code base!

Functor



template <class FunctorType>
class PlatformFileFunctor : public IPlatformFile::FDirectoryVisitor	//GenericPlatformFile.h
{
public:
	
	virtual bool Visit(const TCHAR* FilenameOrDirectory, bool bIsDirectory) override
	{
		return Functor(FilenameOrDirectory, bIsDirectory);
	}

	PlatformFileFunctor(FunctorType&& FunctorInstance)
		: Functor(MoveTemp(FunctorInstance))
	{
	}

private:
	FunctorType Functor;
};

template <class Functor>
PlatformFileFunctor<Functor> MakeDirectoryVisitor(Functor&& FunctorInstance)
{
	return PlatformFileFunctor<Functor>(MoveTemp(FunctorInstance));
}




//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//  Victory Get All Files
//      Optional File Extension Filter!!!  by Rama
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
static FORCEINLINE bool GetFiles(const FString& FullPathOfBaseDir, TArray<FString>& FilenamesOut, bool Recursive=false, const FString& FilterByExtension = "")
	{
		//Format File Extension, remove the "." if present
		const FString FileExt = FilterByExtension.Replace(TEXT("."),TEXT("")).ToLower();
		
		FString Str;
		auto FilenamesVisitor = MakeDirectoryVisitor(
			&](const TCHAR* FilenameOrDirectory, bool bIsDirectory) 
			{
				//Files
				if ( ! bIsDirectory)
				{
					//Filter by Extension
					if(FileExt != "")
					{
						Str = FPaths::GetCleanFilename(FilenameOrDirectory);
					
						//Filter by Extension
						if(FPaths::GetExtension(Str).ToLower() == FileExt) 
						{
							if(Recursive) 
							{
								FilenamesOut.Push(FilenameOrDirectory); //need whole path for recursive
							}
							else 
							{
								FilenamesOut.Push(Str);
							}
						}
					}
					
					//Include All Filenames!
					else
					{
						//Just the Directory
						Str = FPaths::GetCleanFilename(FilenameOrDirectory);
						
						if(Recursive) 
						{
							FilenamesOut.Push(FilenameOrDirectory); //need whole path for recursive
						}
						else 
						{
							FilenamesOut.Push(Str);
						}
					}
				}
				return true;
			}
		);
		if(Recursive) 
		{
			return FPlatformFileManager::Get().GetPlatformFile().IterateDirectoryRecursively(*FullPathOfBaseDir, FilenamesVisitor);
		}
		else 
		{
			return FPlatformFileManager::Get().GetPlatformFile().IterateDirectory(*FullPathOfBaseDir, FilenamesVisitor);
		}
	}	




	//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
	//  Victory Get Directories
	//      Optional Search SubString!!!  by Rama
	//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
	//Get Directories
	static FORCEINLINE bool GetDirectories(const FString& FullPathOfBaseDir, TArray<FString>& DirsOut, bool Recursive=false, const FString& ContainsStr="")
	{
		FString Str;
		auto FilenamesVisitor = MakeDirectoryVisitor(
			&](const TCHAR* FilenameOrDirectory, bool bIsDirectory) 
			{
				if (bIsDirectory)
				{
					//Using a Contains Filter?
					if(ContainsStr != "")
					{
						Str = FPaths::GetCleanFilename(FilenameOrDirectory);
						
						//Only if Directory Contains Str
						if(Str.Contains(ContainsStr))
						{
							if(Recursive) DirsOut.Push(FilenameOrDirectory); //need whole path for recursive
							else DirsOut.Push(Str);
						}
					}
					
					//Get ALL Directories!
					else
					{
						//Just the Directory
						Str = FPaths::GetCleanFilename(FilenameOrDirectory);
						
						if(Recursive) DirsOut.Push(FilenameOrDirectory); //need whole path for recursive
						else DirsOut.Push(Str);
					}
				}
				return true;
			}
		);
		if(Recursive) 
		{
			return FPlatformFileManager::Get().GetPlatformFile().IterateDirectoryRecursively(*FullPathOfBaseDir, FilenamesVisitor);
		}
		else 
		{
			return FPlatformFileManager::Get().GetPlatformFile().IterateDirectory(*FullPathOfBaseDir, FilenamesVisitor);
		}
	}	
}; 



**Absolute Paths**

Please note that the paths that you pass in to my above functions must be fully qualified / absolute paths.

You can use my wiki on path functions to get such a path.

**Rama's Wiki on Getting Absolute Paths to Your UE4 Project Files**
https://wiki.unrealengine.com/Packaged_Game_Paths,_Obtain_Directories_Based_on_Executable_Location

Enjoy!

https://www.mediafire.com/convkey/a416/xh2a0w6qocsc9xb6g.jpg

Rama

Thank you so much both of you for taking the time to help me out.

Rawa, I’m just starting out with c++, so I’m afraid I have some very basic beginner issues with your code.
I added your code and included the GetFiles() function to the .h file.
When I compile the code VS2013 says: Error 1 error C3861: ‘MakeDirectoryVisitor’: identifier not found
I guess that is because I need to define MakeDirectoryVisitor too in the .h files too, but I don’t know how.

Sorry for the noob question, C++ is really new to me.

Thanks again for your help,
Rick

EDIT: CPP file:



#include "RealisticRendering.h"
#include "FileBrowser.h"

AFileBrowser::AFileBrowser()
{
}

void AFileBrowser::BeginPlay()
{
	Super::BeginPlay();
}

TArray<FString> AFileBrowser::GetFiles()
{
	TArray<FString> filenames;

	FString Str;
	auto FilenamesVisitor = MakeDirectoryVisitor(
		&](const TCHAR* FilenameOrDirectory, bool bIsDirectory)
	{
		//Files
		if (!bIsDirectory)
		{
				//Just the Directory
				Str = FPaths::GetCleanFilename(FilenameOrDirectory);

				filenames.Push(Str);
		}
	});
	return filenames;
}

template <class FunctorType>
class PlatformFileFunctor : public IPlatformFile::FDirectoryVisitor	//GenericPlatformFile.h
{
public:

	virtual bool Visit(const TCHAR* FilenameOrDirectory, bool bIsDirectory) override
	{
		return Functor(FilenameOrDirectory, bIsDirectory);
	}

	PlatformFileFunctor(FunctorType&& FunctorInstance)
		: Functor(MoveTemp(FunctorInstance))
	{
		return PlatformFileFunctor<Functor>(MoveTemp(FunctorInstance));
	}

private:
	FunctorType Functor;
};

template <class Functor>
PlatformFileFunctor<Functor> MakeDirectoryVisitor(Functor&& FunctorInstance)
{
	return PlatformFileFunctor<Functor>(MoveTemp(FunctorInstance));
}


.h file:



UCLASS()
class REALISTICRENDERING_API AFileBrowser : public AActor
{
    GENERATED_BODY()
    
public:    
    // Sets default values for this actor's properties
    AFileBrowser();

    // Called when the game starts or when spawned
    virtual void BeginPlay() override;
    
    UFUNCTION(BlueprintCallable, Category = "Spawning")
        TArray<FString> GetFiles();

};


mmm take this my friend, is myself awnser maybe the most easy way to do your needs, in the example i find .png because i need find to load as textue but is work for every format is a wild card, you just need add the header to contain the FFileManagerGeneric get fuction i dont remenber the header name jaja, search for in de UE docs ok

https://answers.unrealengine.com/questions/188001/ifilemanager-and-ifilemanagergeneric-return-null-f.html

Thank you zkarma. Your solution worked perfectly!

Just for people, who has the same problem. Rama code works perfectly. RickDangerous had to add the Functor code, which posted Rama here, to the header.

That’s very useful, but this caught my eye:

Surely by contributing the code to Epic you lose any rights to the code, including the right to force attribution? I am not a lawyer, so I might be way off here.