8

I have this code to copy all files from source-directory, F:\, to destination-directory.

public void Copy(string sourceDir, string targetDir)
{
  //Exception occurs at this line.
    string[] files = System.IO.Directory.GetFiles(sourceDir, "*.jpg", 
                                             SearchOption.AllDirectories);

    foreach (string srcPath in files)
    {
       File.Copy(srcPath, srcPath.Replace(sourceDir, targetDir), true);
    }
}

and getting an exception.

If I omit SearchOption.AllDirectories and it works but only copies files from F:\

David Heffernan
  • 601,492
  • 42
  • 1,072
  • 1,490
Umair Ayub
  • 19,358
  • 14
  • 72
  • 146

4 Answers4

5

Use following function instead of System.IO.Directory.GetFiles:

IEnumerable<String> GetAllFiles(string path, string searchPattern)
    {
        return System.IO.Directory.EnumerateFiles(path, searchPattern).Union(
            System.IO.Directory.EnumerateDirectories(path).SelectMany(d =>
            {
                try
                {
                    return GetAllFiles(d,searchPattern);
                }
                catch (UnauthorizedAccessException e)
                {
                    return Enumerable.Empty<String>();
                }
            }));
    }
Bohdan
  • 468
  • 5
  • 6
  • 1
    Could you maybe explain why this would help? – Robin Ellerkmann Feb 19 '15 at 16:26
  • This way you will catch the exception on unaccessible directories and at the same time get all accessible files without exception in your code. – Bohdan Feb 19 '15 at 16:49
  • Simply, when the function System.IO.Directory.GetFiles throws exception suggested function does not throw anything and so you are able to continue to your foreach cycle. – Bohdan Feb 19 '15 at 16:56
2

File system objects are subject to security. Some file system objects are secured in such a way that they can only be accessed by certain users. You are encountering a file to which the user executing the code does not have sufficient rights to access.

The reason that you don't have access rights for this particular folder is to protect the security of the different users on the system. The folder in question is the recycle bin on that drive. And each different user has their own private recycle bin, that only they have permission to access. If anybody could access any other user's recycle bin, then users would be able to read each other's files, a clear violation of the system's security policy.

Perhaps the simplest way around this is to skip hidden folders at the root level of the drive. That simple change would be enough to solve your problem because you surely don't want to copy recycle bins.

David Heffernan
  • 601,492
  • 42
  • 1,072
  • 1,490
0

That folder is a secure system folder (your bin, each drive has its own bin). Just place your file.copy into a try catch statement and ignore/log all the failures. That way you will only copy actual files and skip system files/folders.

If you really want to avoid the try catch statement. Use the fileinfo and directory info classes to figure out which folders/files are of the system and will throw an exception.

woutervs
  • 1,500
  • 12
  • 28
0

This should do the trick:

private IEnumerable<string> RecursiveFileSearch(string path, string pattern, ICollection<string> filePathCollector = null)
{
    try
    {
        filePathCollector = filePathCollector ?? new LinkedList<string>();

        var matchingFilePaths = Directory.GetFiles(path, pattern);

        foreach(var matchingFile in matchingFilePaths)
        {
            filePathCollector.Add(matchingFile);
        }

        var subDirectories = Directory.EnumerateDirectories(path);

        foreach (var subDirectory in subDirectories)
        {
            RecursiveFileSearch(subDirectory, pattern, filePathCollector);
        }

        return filePathCollector;
    }
    catch (Exception error)
    {
        bool isIgnorableError = error is PathTooLongException ||
            error is UnauthorizedAccessException;

        if (isIgnorableError)
        {
            return Enumerable.Empty<string>();
        }

        throw error;
    }
}
sspaniel
  • 647
  • 3
  • 10