Move files from multiple directories to one

 
Below is a simple code snippet to move files from multiple recursive directories into a separate directory.
e.g. Let's say I have a directory called 'Music' and it contains directories like 'Album1', 'Album2' etc. Then below code will moves all the files (not the directories) from Album1 and Album2 to specified directory.




arguments: 
   source: source directory path (Path to the directory 'Music' in above example).
   target: path of the directory where you want to move the files.



        static void Do(string source, string target)
        {
            foreach (var src in Directory.GetDirectories(source))
            {
                foreach (var file in Directory.GetFiles(src.ToString()))
                {
                    FileInfo f = new FileInfo(file);
                    File.Move(file, target + "\\" + f.Name);
                }

                foreach (var dir in Directory.GetDirectories(src.ToString()))
                {
                    Do(src.ToString(), target);
                }
            }
        }

ref and out parameters in C#

ref and out both are types of passing arguments by reference to a function, only the rules to use them are slightly different which actually are decisive for us on where they should be used.
When passing parameters with 'out' it is must for the function to assign (or modify) the values of parameters, otherwise the compiler givers compile time error. It is fine even if we don't assign values to them before passing, compiler guarantees that they will be initialized in the function.
When passing parameters with 'ref' type, it is fine even if the called function doesn't assign or modify their values but they must be initialized before passing to the function.
Consider following example:

public static void swap( ref int n1, ref int n2) { int temp = n1; n1 = n2; n2 = temp; }
This function takes 2 parameters by 'ref' type and the functions swaps their values inside the body.
int num1 = 40; int num2 = 50; swap( ref num1, ref num);
After this function call the values of num1 and num2 will be 50 and 40 resp. Now let's look at an example of 'out' parameters.
public static void calculate(float radius, out double area, out double circum) { area = 3.14 * radius * radius; circum = 2 * 3.14 * radius; }

Here the function calculate(), takes two arguments of type 'out' and assigns some values to them (area and circumference of a circle with no surprise). Here, if the function doesn't assign the value to out arguments compiler throws an error.
public static void calculate(float radius, out double area, out double circum) { //area = 3.14 * radius * radius; circum = 2 * 3.14 * radius; }

If we comment out the line assigning value to the variable area, then we will get an error as:
The out parameter 'area' must be assigned to before control leaves the current method.
Conclusion:
  • ref and out both are types of passing parameters by reference.
  • ref should be used where we are not sure that the calling function will definitely change parameter's value.
  • out should be used where it is guaranteed that calling function will assign value to the parameter.
If we don't know how many arguments may be passed to our function or this number is not fixed then in such cases there is another type of parameter passing in C#, where parameters are received by the function with 'params' keyword. Go to this post to read about it.

params keyword in C#

params keyword allows to specify a method with parameter which takes variable number of arguments. It is an array type of parameter. With this type of parameter you can call a method each time with different number of arguments.
public static int Sum(params int[] args)
{
   int sum = 0;
   foreach (int ele in args)
      sum += ele;
   return sum;
}

Function Sum() shown in above code accepts parameter of type params. You can see that the parameter is same as array type,  but it differs from array in several ways
  • here you can pass multiple int elements instead of single array element.
  • size is not fixed, each time you may pass different no of elements
  • you can also call Sum() without passing single parameter in which case here, this function will return 0.
You can call Sum() as:
Sum(1, 2);                    // will return 3
Sum(new int[] { 1, 2, 3 });   // will return 6
Sum();                        // will return 0

Points to note while using params:
  • Each function can only have one params type of parameter
  • It must be the last parameter in argument list
  • It is perfectly fine even if you don't pass any parameter for params type of parameter.

Value types and ref types in C#

value types and ref types are the types of data types classified on the basis of their allocation on stack and heap respectively.
value type variables directly contains the value which is assigned to them and these are stored on stack whereas reference type variables contain the reference of the data which they are assigned and the data is stored in the memory on heap.
All the basic data types in C# along with struct and enum are value types.
All value types are derived implicitly from System.ValueType
When we declare an integer in a program;
int X = 5;
variable declaration
memory for the variable is allocated on the stack and the variable is assigned with the initial value if given otherwise with the default value of that type.Every value type has an implicit default constructor which does this.
Now when we assign X to another variable,
int Y = X;

variable declaration
memory for Y is created on the stack and value of X is assigned(copied) to Y.
Now consider when we declare a reference type variable (an object of a class)
MyClass obj1 = new MyClass();
img3
memory for data which MyClass holds is allocated on the heap and only the reference of this data is stored in the variable obj1, which is stored on the stack.
When obj1 is assigned to another variable:
MyClass obj2 = obj1;
img4
Unlike value type variables here, the actual data is not again copied in the memory. Here obj2 also contains a reference to the data similar to oobj1.
Now when obj1 goes out of scope, the data still remains on the heap and only the reference of that data from obj1 is removed.
img5
Similarly if, obj2 also goes out of scope the reference of data from obj2 is also deleted but the data still remains in the memory. This data is now unreferenced block in the memory which is available for garbage collection. Garbage collector in C# automatically detects such unreferenced blocks in memory and frees the memory by deleting them unlike in C++ where we need to explicitly delete it.

C# Program For Renaming Files In Folder


Sometimes you may want to rename all the files in a directory,
e.g. If all the files are starting with some special character or string like "IMG_"

Manually this task will be very difficult. Here's a program in C# to rename all the files in a directory.

        static void Main(string[] args)
        {
            // directory_path - replace this with path of directory containing files to rename.
            DirectoryInfo dir = new DirectoryInfo("directory_path");
            FileInfo[] files = dir.GetFiles();           
            String fileName = "";

            foreach (FileInfo f in files)
            {
                fileName = f.Name;
                ChangeFileName(ref fileName);
                if (f.Name != fileName)
                    File.Move(f.FullName, f.DirectoryName + "\\" + fileName);
            }
        }

        //======================================================
        // code to change file name as per your requirement.
        //======================================================
        static void ChangeFileName(ref String fileName)
        {
            fileName = fileName.TrimStart();          
            fileName = fileName.Replace("IMG_", "");          
            fileName = fileName.TrimStart();
        }

To remove the digits in a file name you can use following Regular expression in ChangeFileName method
   
       fileName = Regex.Replace(fileName, @"\d", "");

While doing this you need to be careful. In case of file extensions like '.mp3' use of above line will remove 3 from 'mp3' as well.