Concatenating folder names to file name and copy file to a folde - c#

My folder structure is as .. temp\2016\09\11\16
In the last folder I have multiple text/json files.
I would like to run a console application that would loop through every folder and rename the files with foldernames concatenated.
So a file abcd.json would become 2016091116_abcd.json
Then copy this file to another folder.
I tried..
using System;
using System.IO;
using System.Collections;
namespace concatdf
{
class Program
{
static void Main(string[] args)
{
string folderPath = "D:\\500GBNP\\Projects\\temp";
DirectoryInfo startDir = new DirectoryInfo(folderPath);
RecurseFileStructure recurseFileStructure = new RecurseFileStructure();
recurseFileStructure.TraverseDirectory(startDir);
}
public class RecurseFileStructure
{
public void TraverseDirectory(DirectoryInfo directoryInfo)
{
var subdirectories = directoryInfo.EnumerateDirectories();
foreach (var subdirectory in subdirectories)
{
TraverseDirectory(subdirectory);
}
var files = directoryInfo.EnumerateFiles();
foreach (var file in files)
{
HandleFile(file);
}
}
void HandleFile(FileInfo file)
{
string destfolderPath = "D:\\500GBNP\\Projects\\temp1\\";
file.CopyTo(destfolderPath+file.Name);
}
}
}
}
With the above code I'm able to traverse and copy all files to target directory but file names do not get concatenated with foldernames.
So a file abcd.json in folder temp\2016\09\11\16 would become 2016091116_abcd.json and all files get copied to temp1 folder.
I would sincerely appreciate if someone could help.

You can append the folder name in each recursion and append the destination filename.
using System;
using System.IO;
using System.Collections;
namespace concatdf
{
class Program
{
static void Main(string[] args)
{
string folderPath = "D:\\500GBNP\\Projects\\temp";
DirectoryInfo startDir = new DirectoryInfo(folderPath);
RecurseFileStructure recurseFileStructure = new RecurseFileStructure();
recurseFileStructure.TraverseDirectory(startDir, string.Empty);
}
public class RecurseFileStructure
{
public void TraverseDirectory(DirectoryInfo directoryInfo, string fileAppend)
{
var subdirectories = directoryInfo.EnumerateDirectories();
foreach (var subdirectory in subdirectories)
{
TraverseDirectory(subdirectory, fileAppend + subdirectory.Name);
}
var files = directoryInfo.EnumerateFiles();
foreach (var file in files)
{
HandleFile(file, fileAppend);
}
}
void HandleFile(FileInfo file, string fileAppend)
{
string destfolderPath = "D:\\500GBNP\\Projects\\temp1\\";
file.CopyTo(destfolderPath + fileAppend +"_"+ file.Name);
}
}
}
}

We just need to make HandleFile a bit more intelligent. Let's take the last 4 folder names and add it to the name..
void HandleFile(FileInfo file)
{
string destfolderPath = "D:\\500GBNP\\Projects\\temp1\\";
var pathBits = file.DirectoryName.Split(Path.DirectorySeparatorChar, Path.AltDirectorySeparatorChar);
var s = string.Concat(pathBits[^4..]);
file.CopyTo(Path.Combine(destfolderPath, s+'_'+file.Name));
}
This renames the file as it copies (which seemed a more sensible way to go, to me). If you truly want to rename the file before you copy, insert a call to FileInfo.MoveTo() after you copy
Strive to use Path when working with paths, not string concatenation

What about something simpler like this?:
public static void CopyFiles(DirectoryInfo sourceDirectory, DirectoryInfo targetDirectory)
{
// This will provide all files in sourceDirectory and nested directories
foreach (var file in sourceDirectory.EnumerateFiles("*", SearchOption.AllDirectories))
{
// work out what the relative path from sourceDirectory is
// e.g. 2016\09\11\16\abcd.json
string relativePath = Path.GetRelativePath(sourceDirectory.FullName, file.FullName);
// get the directory part and replace the separator with an empty string (this could be
// made more efficient)
string directoryPart = Path.GetDirectoryName(relativePath)
.Replace(Path.DirectorySeparatorChar.ToString(), string.Empty);
// get just the filename
string filePart = Path.GetFileName(relativePath);
// combine the target directory, the directory part, and the filename part
// I've made the assumption that you don't want files in the base directory
// to be called _filename, so we just use filePart when there is no directoryPart
string newFileName = string.IsNullOrEmpty(directoryPart) ? filePart : $"{directoryPart}_{filePart}";
string newFullName = Path.Combine(targetDirectory.FullName, newFileName);
// copy the file to the new location
file.CopyTo(newFullName);
}
}

Related

Rename file 20181207_ProdAndPressuresExport.csv to ProdAndPressuresExport.csv

I have the following C# code but having issues renaming the file to what I want (ProdAndPressuresExport.csv). It is renaming the file as ProdAndPressuresExportProdAndPressuresExport.csv and also moving the rename file up 1 folder. I would like for it to stay in its original file path C:\TEMP\CSVFile\ProdAndPressuresExport. Please help.
namespace ConsoleApp1
{
class Program
{
static void Main(string[] args)
{
const string DIRECTORY_PATH = #"C:\TEMP\CSVFile\ProdAndPressuresExport";
const string FILE_NAME_TEMPLATE = "*_ProdAndPressuresExport.CSV";
if (Directory.Exists(DIRECTORY_PATH))
{
string[] filePathList = Directory.GetFiles(DIRECTORY_PATH, FILE_NAME_TEMPLATE);
foreach (string filePath in filePathList)
{
if (File.Exists(filePath))
{
string newName = DIRECTORY_PATH + filePath.Split('_')[1];
File.Move(filePath, newName);
}
}
}
}
}
}
Always use Path.Combine to construct paths, rather than string concatenation.
string newName = DIRECTORY_PATH + filePath.Split('_')[1];
Should be
string newName = Path.Combine(DIRECTORY_PATH, filePath.Split('_')[1]);
Otherwise you miss the directory separator character, and your file will end up in the parent folder above your intended folder with an unintentionally concatenated name.

C# copying folders from server

using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;
using System.IO;
namespace Application2
{
public partial class Form1 : Form
{
public Form1()
{
InitializeComponent();
}
private void Btn_search_Click(object sender, EventArgs e)
{
//Uses the text entered by user
//searchAndCopy(txtbox1.Text);
//Uses file for copy process
searchAllLines(#"D:\Icyer\liste2.txt");
}
private void searchAllLines(string filename)
{
foreach (string line in File.ReadLines(filename))
{
searchAndCopy(line);
}
}
private void searchAndCopy(string textToSearch)
{
// MessageBox.Show("|" + textToSearch + "|");
string srcfolder = #"X:\xxxx\xxxx\xxxx\xxxx";
DirectoryInfo Ordner = new DirectoryInfo(srcfolder);
FileInfo[] Pfad = Ordner.GetFiles("*" + textToSearch + "*", SearchOption.AllDirectories);
foreach (var item in Pfad)
{
string destinationDirectory = #"D:\xxxx\Copy\";
//Directory.CreateDirectory(destinationDirectory);
string[] substrings = item.FullName.Split('\\');
string folder = substrings[srcfolder.Split('\\').Length - 1];
if(folder == textToSearch) {
DirectoryCopy(srcfolder + folder, destinationDirectory + folder, true);
}
//File.Copy(item.FullName, item.Name);
}
}
private static void DirectoryCopy(string sourceDirName, string destDirName, bool copySubDirs)
{
DirectoryInfo dir = new DirectoryInfo(sourceDirName);
DirectoryInfo[] dirs = dir.GetDirectories();
// If the source directory does not exist, throw an exception.
if (!dir.Exists)
{
throw new DirectoryNotFoundException(
"Source directory does not exist or could not be found: " + sourceDirName);
}
// If the destination directory does not exist, create it.
if (!Directory.Exists(destDirName))
{
Directory.CreateDirectory(destDirName);
}
// Get the file contents of the directory to copy.
FileInfo[] files = dir.GetFiles();
foreach (FileInfo file in files)
{
// Create the path to the new copy of the file.
string temppath = Path.Combine(destDirName, file.Name);
try
{
// Copy the file.
file.CopyTo(temppath, false);
}
catch { };
}
// If copySubDirs is true, copy the subdirectories.
if (copySubDirs)
{
foreach (DirectoryInfo subdir in dirs)
{
// Create the subdirectory.
string temppath = Path.Combine(destDirName, subdir.Name);
// Copy the subdirectories.
DirectoryCopy(subdir.FullName, temppath, copySubDirs);
}
//MessageBox.Show("Done!");
}
}
}
}
The code works perfectly fine when I try to copy from "D: to D:", when I try to change the code from
string srcfolder = #"D:\xxxx\xxxx\";
to
string srcfolder = #"X:\xxxx\xxxx\xxxx\xxxx";
The application freezes the second I press on the button. Can someone tell me if it has to do because I'm trying to copy files from a server or is there an error in the code somewhere. Access to the server is granted and I have rights to copy files. Destination should stay on "D:". "X:" to "X:" doesnt work either, Application freezes the second the button is pressed.
As your comments indicate there are to many files in the directory and you are retrieving all and then iterating them again in your sub function. A local disk is always much faster than a network location - also perhaps you just have some test data in your local disk and not the whole tree mirrored.
In general you should offload your processing into a separate thread - this way you can pass back 'status information' to your gui thread and display them (the application will not stale anymore).
With this line:
FileInfo[] Pfad = Ordner.GetFiles("*" + textToSearch + "*", SearchOption.AllDirectories);
you retrieve all files which match your textSearch string in all sub directories. Depending on the number of files and directories this can take a very long time.
Perhaps it would be better to iterate each directory recursive checking the content if something does need to get copied?
About offloading to another thread you can take a look here

Filter Directory structure by Created date and then Copy using c#

I want to Filter files in an entire directory structure by created date property and then copy preserving this new filtered directory structure to the destination using c#.
I Have found a solution, but it does not filter.
using System;
using System.IO;
class CopyDir
{
public static void Copy(string sourceDirectory, string targetDirectory)
{
DirectoryInfo diSource = new DirectoryInfo(sourceDirectory);
DirectoryInfo diTarget = new DirectoryInfo(targetDirectory);
CopyAll(diSource, diTarget);
}
public static void CopyAll(DirectoryInfo source, DirectoryInfo target)
{
Directory.CreateDirectory(target.FullName);
// Copy each file into the new directory.
foreach (FileInfo fi in source.GetFiles())
{
Console.WriteLine(#"Copying {0}\{1}", target.FullName, fi.Name);
fi.CopyTo(Path.Combine(target.FullName, fi.Name), true);
}
// Copy each subdirectory using recursion.
foreach (DirectoryInfo diSourceSubDir in source.GetDirectories())
{
DirectoryInfo nextTargetSubDir =
target.CreateSubdirectory(diSourceSubDir.Name);
CopyAll(diSourceSubDir, nextTargetSubDir);
}
}
public static void Main()
{
string sourceDirectory = #"c:\sourceDirectory";
string targetDirectory = #"c:\targetDirectory";
Copy(sourceDirectory, targetDirectory);
}
// Output will vary based on the contents of the source directory.
}
Well after you told us you want to "filter" by the creation date you could do something like:
//If date is newer than 1 week
if(fi.CreationTime >= DateTime.Now - TimeSpan.FromDays(7))
fi.CopyTo(Path.Combine(target.FullName, fi.Name), true);

Copy all files in subfolders to another folder using c# with subfolder name

My source path is C:\images\ in which I have hundreds of folders called Album-1, Album-2 etc. I create a target path F:\AllPics. And then I want to move all the files inside my albums to the target path, so that I get all the images in one folder with subfolder names like album-1_img1,album2-img2. How can I do this ?
namespace MassFileMoverConsole
{
class Program
{
string _sourcePath;
string _targetPath;
static void Main(string[] args)
{
Program massMover = new Program();
massMover.MoveThemAll();
}
void MoveThemAll()
{
Console.WriteLine("Enter source path : ");
_sourcePath = Console.ReadLine();
Console.WriteLine("Enter target path : ");
_targetPath = Console.ReadLine();
var subFolderNamesTargetPath = Directory.GetDirectories(_sourcePath);
foreach(var subFolderName in subFolderNamesTargetPath)
{
var subFolder = new DirectoryInfo(subFolderName);
var subFolderFiles = subFolder.GetFiles();
foreach(var subFolderFile in subFolderFiles)
{
var fileNewName = subFolder.Name + "_" + subFolderFile.Name;
subFolderFile.CopyTo(Path.Combine(_targetPath, fileNewName));
}
}
}
}
}
Look at the File & Directory classes.
You can iterate through the files in a directory similar to this (may need tweeks)
There are options to include directories etc.
// Process the list of files found in the directory.
string [] fileEntries = Directory.GetFiles(targetDirectory);
foreach(string fileName in fileEntries)
ProcessFile(fileName);
// Recurse into subdirectories of this directory.
string [] subdirectoryEntries = Directory.GetDirectories(targetDirectory);
foreach(string subdirectory in subdirectoryEntries)
ProcessDirectory(subdirectory);

How can I find a file within any description of path?

I need find the specific file/folder on my hard drive.
For example i need find a file (do1.bat) and then store the path of the file. But i dont know where can it be stored, so i have to scan all hard drive.
How can i use C# for this?
A simple way would be
var results = Directory.GetFiles("c:\\", "do1.bat", SearchOption.AllDirectories);
This would recurse through all directory and collect all files named do1.bat. Unfortunatly this will not work on complete c:\ since it will throw exceptions if you don't have access to a directory, which surely will happen.
So this is a recursive version:
private static void FindFile(DirectoryInfo currentDirectory, string pattern, List<FileInfo> results)
{
try
{
results.AddRange(currentDirectory.GetFiles(pattern, SearchOption.TopDirectoryOnly));
foreach (DirectoryInfo dir in currentDirectory.GetDirectories("*", SearchOption.TopDirectoryOnly).Where(d => d.Name != "." && d.Name != ".."))
FindFile(dir, pattern, results);
}
catch
{
// probably no access to directory
}
}
This recurses through the directory tree and tries to get the files in a directory and then all subdirectories (except . and ..).
You can use it this way:
DirectoryInfo d = new DirectoryInfo("c:\\");
List<FileInfo> results = new List<FileInfo>();
FindFile(d, "do1.bat", results);
This will find all files named do1.bat in any subdirectory of C:\\ and enlist the FileInfos in the results list.
this should provide you a list of files, matching your search pattern
string[] Result = Directory.GetFiles(#"C:\", "do1.bat", SearchOption.AllDirectories);
Refer: https://msdn.microsoft.com/en-us/library/07wt70x2(v=vs.110).aspx
List<string> lstfilepaths = new List<string>();
public static void ProcessDirectory(string targetDirectory)
{
// Process the list of files found in the directory.
string [] fileEntries = Directory.GetFiles(targetDirectory);
foreach(string fileName in fileEntries) // included as per your logic
{
if(fileName == "do1.bat")
{
ProcessFile(fileName);
}
}
// Recurse into subdirectories of this directory.
string [] subdirectoryEntries = Directory.GetDirectories(targetDirectory);
foreach(string subdirectory in subdirectoryEntries)
ProcessDirectory(subdirectory);
}
public static void ProcessFile(string path)
{
lstfilepaths.Add(path);
}
For one file:
public string FindFileByName(string fileName, string searchPath)
{
string resultPath = null;
DirectoryInfo directoryInWhichToSearch = new DirectoryInfo(searchPath);
FileInfo foundFile = directoryInWhichToSearch.GetFiles(fileName, SearchOption.AllDirectories)[0];
resultPath = foundFile.FullName;
return resultPath;
}
You can then use it like this:
string fileFullPath = FindFileByName("do1.bat", #"C:\");

Categories

Resources