12shadow12 February 2016

Generate list of files in directory with relative path

So, I'm making a little app which generates a list of files inside a folder (recursive) from a command line argument. I would like it to generate the file list with relative paths so I can use them later. The command like argument folder is c:/folder, so I want to get everything inside the folder not including the folder itself.

This is what I get now

c:/folder\some.exe  
c:/folder\locales\en.pak  
c:/folder\logs\client_2016.log

This is what I would like.

some.exe  
locales\en.pak  
logs\client_2016.log

code

public static void ProcessDirectory(string targetDirectory)
    {
        // Process the list of files
        string[] fileEntries = Directory.GetFiles(targetDirectory);
        Parallel.ForEach(fileEntries, fileEntry =>
        {
            ProcessFile(fileEntry);
        });

        // Recurse into subdirectories
        string[] subdirectoryEntries = Directory.GetDirectories(targetDirectory);
        Parallel.ForEach(subdirectoryEntries, subdirectoryEntry =>
        {
            ProcessDirectory(subdirectoryEntry);
        });
    }

    public static void ProcessFile(string path)
    {

        //string output = path.Replace(Environment.GetCommandLineArgs, ""); Something like this maybe?
        //Console.WriteLine(output);
        Console.WriteLine(path);
    }

Answers


dibs487 February 2016

Pass the initial directory to your method?

public static void ProcessDirectory(string targetDirectory)
{
    ProcessDirectory(targetDirectory, targetDirectory);
}   

public static void ProcessDirectory(string targetDirectory, string pathToRemove)
{
    // Process the list of files
    string[] fileEntries = Directory.GetFiles(targetDirectory);
    Parallel.ForEach(fileEntries, fileEntry =>
    {
         ProcessFile(fileEntry, pathToRemove);
    });

    // Recurse into subdirectories
    string[] subdirectoryEntries = Directory.GetDirectories(targetDirectory);
    Parallel.ForEach(subdirectoryEntries, subdirectoryEntry =>
    {
        ProcessDirectory(subdirectoryEntry, pathToRemove);
    });
}

public static void ProcessFile(string path, string pathToRemove)
{
    Console.WriteLine(path.Replace(pathToRemove,""));
}


Matthew Watson February 2016

You don't need to handle the recursion yourself; you can use the overload of Directory.EnumerateFiles() which takes a SearchOption parameter.

Provided that your root starts with a drive letter or \\, you can do what you want like this:

string root = @"D:\Test\";

var files = Directory.EnumerateFiles(root, "*", SearchOption.AllDirectories)
    .Select(path => path.Replace(root, ""));

// Now files contains all the file names you want, with the root removed.

Console.WriteLine(string.Join("\n", files));

Note that the file entries are not fetched until you enumerate them. You can put them all in a list like so:

var listOfFiles = files.ToList();

Or you can just use foreach to iterate over them without putting them in a list first.

foreach (var file in files)
{
    // Do something with file.
}


Jure Potocnik February 2016

Something like this?

var files = GetFiles(@"C:/tmp/", @"C:/tmp/");
return;

 public static List<string> GetFiles(string path, string basePath)
    {
      var files = System.IO.Directory.GetFiles(path).ToList().Select(m => m.Replace(basePath, "")).ToList();
      foreach (var directory in System.IO.Directory.GetDirectories(path))
      {
        files.AddRange(GetFiles(directory, basePath));
      }
      files = files.Select(m => m.Replace(basePath, "")).ToList();
      return files;
    }

Post Status

Asked in February 2016
Viewed 3,084 times
Voted 5
Answered 3 times

Search




Leave an answer