using System; using System.IO; using System.Linq; namespace TwoFour { /// /// Depth changing processor /// public class Processor { /// /// Directory to process /// private string directory; /// /// Number of bytes deep the folder should be rebuilt to /// private int depth; /// /// Create a new processor /// /// Directory to process /// Byte depth public Processor(string directory, int depth) { this.directory = directory; this.depth = depth; } /// /// Process a given directory in the requested way /// /// True if the folder was processed, false on unrecoverable error public bool ProcessFolder() { try { // Get the full path for processing directory = Path.GetFullPath(directory); if (!Directory.Exists(directory)) throw new DirectoryNotFoundException(); // Make sure it ends with a directory separator if (!directory.EndsWith("\\")) directory += "\\"; } catch { Console.WriteLine($"{directory} is not a valid directory"); return false; } Console.WriteLine($"Traversing {directory} and rebuilding to {depth}-deep folders"); foreach (string file in Directory.EnumerateFiles(directory, "*", SearchOption.AllDirectories)) { Console.WriteLine($"Processing {file}"); // Get relevant parts of the path string oldDir = Path.GetDirectoryName(file); string current = oldDir.Substring(directory.Length); string filename = Path.GetFileName(file); // Make sure subdirectory ends with a directory separator if (!current.EndsWith("\\")) current += "\\"; // Get the expected new subdirectory string expected = GetSubdirectory(filename); // If we have a match between current and expected, don't do anything if (string.Equals(current, expected, StringComparison.OrdinalIgnoreCase)) { Console.WriteLine($"{file} already in the right directory!"); continue; } // Get the new full path to the output directory string subdirectory = Path.Combine(directory, expected); // Make sure subdirectory ends with a directory separator if (!subdirectory.EndsWith("\\")) subdirectory += "\\"; // If the directory doesn't exist, create it if (!Directory.Exists(subdirectory)) { try { Console.WriteLine($"Creating {subdirectory}"); Directory.CreateDirectory(subdirectory); } catch (Exception ex) { Console.WriteLine($"An exception occurred while creating {subdirectory}: {ex}"); continue; } } // Now move the file accordingly try { Console.WriteLine($"Moving {filename}"); File.Move(file, Path.Combine(subdirectory, filename)); } catch (Exception ex) { Console.WriteLine($"An exception occurred while moving {filename}: {ex}"); continue; } // If the old path is a subset of the new path and it's empty, remove it if (current.Contains(expected) && Directory.EnumerateFiles(oldDir, "*", SearchOption.AllDirectories).Any()) { try { Console.WriteLine($"Removing {oldDir}"); Directory.Delete(oldDir); } catch (Exception ex) { Console.WriteLine($"An exception occurred while removing {oldDir}: {ex}"); continue; } } } return true; } /// /// Get the expected subdirectory path for a given file path /// /// Filename to get subdirectory for /// String representing the subdirectory, null on error private string GetSubdirectory(string filename) { // If we don't have a long enough filename, return null if (filename.Length < 2 * depth) return null; // Otherwise, get the proper value string path = string.Empty; for (int i = 0; i < depth; i++) { path += $"{filename.Substring(i * 2, 2)}\\"; } return path; } } }