I'm a newbish C#er and here's my question:
What I want:
Copy mp3 files of the same Artist into the same Folder.
e.G. Nirvana - Song 1 & Nirvana - Song 2 into Folder "Nirvana".
What I've been doing so far:
Read ParantDirectory and List the ingredients into a Listbox. The Listbox shows only the Artist (of course its filtered(Substring(indexof"-"))). After the files have been read my tool create a Folder with the Artist name.
And there I'm struggling!
I need a snippet that copy all content of Nirvana* to the Nirvana Folder.
I really hope you girls and guys understand what I'm trying to do...
Thank you in advance!
Greetings from Germany,
ceteus
edit:"here's my code"
void Button1Click(object sender, EventArgs e)
{
listBox1.Items.Clear();
DirectoryInfo ParentDirectory = new DirectoryInfo(#"C:\Users\A7024985\Desktop\_xxx");
label1.Text = ParentDirectory.ToString();
foreach (FileInfo f in ParentDirectory.GetFiles())
{
listBox1.Items.Add(f.Name.Substring(0,f.Name.IndexOf("-"))); //nur den Dateinamen anzeigen in Listbox1
//listBox1.Items.Add(f.Name);
}
// DOPPELTE DATEIEN LĂ–SCHEN in LISTBOX
string[] temp = new string[listBox1.Items.Count];
ArrayList newList = new ArrayList();
for(int i = 0; i< listBox1.Items.Count; i++)
{
temp[i] = listBox1.Items[i].ToString();
}
foreach(string ts in temp)
{
if(!newList.Contains(ts))
{
newList.Add(ts);
}
}
listBox1.Items.Clear();
foreach(string ns in newList)
{
listBox1.Items.Add(ns.ToString());
}
foreach(var listboxitem in listBox1.Items)
{
string pfad = label1.Text + "\\" + listboxitem.ToString();
//DirectoryInfo plop = new DirectoryInfo(name);
//FileInfo[] nPath = plop.GetFiles();
try
{
bool exists = Directory.Exists(pfad);
if(!exists)
{
Directory.CreateDirectory(pfad);
}
}
catch(Exception ex)
{
MessageBox.Show(ex.Message);
}
}
}
void Button2Click(object sender, EventArgs e)
{
listBox2.Items.Clear();
DirectoryInfo ParentDirectory = new DirectoryInfo(#"C:\Users\A7024985\Desktop\_xxx");
foreach (FileInfo f in ParentDirectory.GetFiles())
{
listBox2.Items.Add(f.Name.Substring(0,f.Name.IndexOf("-")));
}
foreach(var listboxitem2 in listBox2.Items)
{
string item;
string umbenannt;
File.Copy(#ParentDirectory + "\\" + listboxitem2.ToString(), #ParentDirectory + "\\");
//listBox1.Items.Add(f.Name.Substring(0,f.Name.IndexOf("-")));
}
}
}
I guess you have a List<FileInfo> containing your files? If so you can go with File.Copy like this:
void Button2Click(object sender, EventArgs e)
{
DirectoryInfo ParentDirectory = new DirectoryInfo(#"C:\Users\A7024985\Desktop\");
string interpret = f.Name.Substring(0, f.Name.IndexOf("-")).TrimEnd(' ');
string title = f.Name.Remove(0, interpret.Length+1).TrimStart(' ');
File.Copy(f.FullName, ParentDirectory
+ interpret
+ "\\"
+ title); //or f.Name
}
Copy("C:\Users\A7024985\Desktop\Nirvana-Teen Spirit.mp3" , C:\Users\A7024985\Desktop\Nirvana\Teen Spirit.mp3
A good way to do this is use the TagLib# library (see example here) to find the ID3 tags (Artist, Song, Album, etc...), and then create a collection of these, and then sort them, and then move them to a new folder based on the Artist.
var songList = new List<string>(); //Contains a list of song files. E.g. "Come As You Are.mp3", "Heart Shaped Box.mp3", "Smells Like Teen Spirit.mp3".
var tagLibFiles = new List<TagLib.File>();
tagLibFiles.AddRange(songList.Select(x => new TagLib.File(x));
var nirvanaSongs = tagLibFiles.Where(x => x.Tag.FirstAlbumArtist == "Nirvana").ToList();
foreach(var song in nirvanaSongs)
{
//Move the file to your Nirvana folder.
}
I am guessing listboxitem.ToString() contains the name of the artist.
Then:
var filestomove = ParentDirectory.GetFiles().Where(f=>f.Name.Contains(listboxitem.ToString()));
foreach(var file in filestomove){
File.Move(file.FullName,pfas+file.Nmae)
}
Related
private void pictureBox2_MouseUp(object sender, MouseEventArgs e)
{
if (e.Button != MouseButtons.Left) return;
if (DrawingRects.Count > 0)
{
// The last drawn shape
var dr = DrawingRects.Last();
if (dr.Rect.Width > 0 && dr.Rect.Height > 0)
{
rectImage = cropAtRect((Bitmap)pictureBox2.Image, dr.Rect);
if (saveRectangles)
{
DirectoryInfo dInfo = new DirectoryInfo(#"d:\rectangles");
var files = GetFilesByExtensions(dInfo, ".bmp");
if (files.Count() > 0)
{
foreach (var f in files)
{
}
}
rectangleName = #"d:\Rectangles\rectangle" + saveRectanglesCounter + ".bmp";
FileList.Add($"{dr.Location}, {dr.Size}", rectangleName);
string json = JsonConvert.SerializeObject(
FileList,
Formatting.Indented // this for pretty print
);
using (StreamWriter sw = new StreamWriter(#"d:\rectangles\rectangles.txt", false))
{
sw.Write(json);
sw.Close();
}
rectImage.Save(rectangleName);
saveRectanglesCounter++;
}
pixelsCounter = rect.Width * rect.Height;
pictureBox1.Invalidate();
listBox1.DataSource = FileList.ToList();
listBox1.SelectedIndex = listBox1.Items.Count - 1;
}
}
}
I'm using DirectoryInfo and the method GetFilesByExtensions
public IEnumerable<FileInfo> GetFilesByExtensions(DirectoryInfo dir, params string[] extensions)
{
if (extensions == null)
throw new ArgumentNullException("extensions");
IEnumerable<FileInfo> files = dir.EnumerateFiles();
return files.Where(f => extensions.Contains(f.Extension));
}
if there are existing files for example rectangle1.bmp rectangle2.bmp.....rectangle7.bmp
then when creating a new rectangle file on the hard disk i want it to be rectangle8.bmp
now it's trying to create another rectangle1.bmp and give exception and i don't want to delete the existing files but to create new ones.
and make it as much as possible generic. but the main goal is to create new files names according to those existing and continue the counting.
You can write a method that checks if the proposed name exists or not
string GetNextName(string baseName, string extension)
{
int counter = 1;
string nextName = baseName + counter + extension;
while(File.Exists(nextName))
{
counter++;
nextName = baseName + counter + extension;
}
return nextName;
}
and call it in this way:
rectangleName = GetNextName(#"d:\Rectangles\rectangle", ".bmp");
You can use linq and do everything in one statement like this:
DirectoryInfo di = new DirectoryInfo(#"D:\rectangles");
var maxIndex = di.GetFiles().Select(fi => fi.Name.Replace("rectangle","").Replace(".bmp", "")).Max(i => i);
private void btn_Backup_Click(object sender, EventArgs e)
{
List<DirectoryInfo> SourceDir = this.lbox_Sources.Items.Cast<DirectoryInfo>().ToList();
List<DirectoryInfo> TargetDir = this.lbox_Targets.Items.Cast<DirectoryInfo>().ToList();
foreach (DirectoryInfo sourcedir in SourceDir)
{
foreach (DirectoryInfo targetdir in TargetDir)
{
string dateString = DateTime.Now.ToString("MM-dd-yyyy_H.mm.ss");
string LogFileName = #"BackupLog_" + sourcedir.Name + #"_" + dateString + #".log";
string[] lines = { dateString + "\t" + sourcedir.FullName + "\t" + targetdir.FullName + "\t" + "COMPLETED" };
if (this.checkbox_zipfiles.Checked == true)
{
System.IO.Compression.ZipFile.CreateFromDirectory(sourcedir.FullName, targetdir.FullName + #"\BACKUP_" + sourcedir.Name + #"_" + dateString + #".zip");
System.IO.File.WriteAllLines(tbox_LogFiles.Text + #"\" + LogFileName, lines);
}
else
{
foreach (var file in sourcedir.GetFiles())
{
Microsoft.VisualBasic.FileIO.FileSystem.CopyDirectory(sourcedir.FullName, targetdir.FullName, true);
System.IO.File.WriteAllLines(tbox_LogFiles.Text + #"\" + LogFileName, lines);
}
}
}
}
}
I need to exclude certain files from the backup (like .txt .docx)
I am using a list on my Form to add those exceptions.
I will also need to exclude certain Files and Folders but I think I can do that if I know how to do this.
private void btn_AddFileTypeException_Click(object sender, EventArgs e)
{
Form_FileTypeExceptions frm = new Form_FileTypeExceptions(new FileException());
if (frm.ShowDialog() == DialogResult.OK)
{
this.lbox_FileTypeExceptions.Items.Add(frm.Exception);
}
}
Any ideas please?
From form where you're setting extensions to be excluded fill list of strings that will contain extensions to skip, something like this:
List<string> extensionsToSkip = new List<string>();
extensionsToSkip.Add(".txt");
extensionsToSkip.Add(".docx");
//etc...
in your inner loop, change foreach loop from
foreach (var file in sourcedir.GetFiles())
into this
foreach (var file in sourcedir.GetFiles()
.Where(f => !extensionsToSkip.Contains(f.Extension)).ToList())
as you can see, when you get file collection with GetFiles it will be filtered to exclude extensions specified in extensionsToSkip list.
before that mentioned loop, test if you're getting right number of files by observing there two lists (just for test):
var originalList = sourcedir.GetFiles();
var filteredList = sourcedir.GetFiles().Where(f => !extensionsToSkip.Contains(f.Extension)).ToList();
Program goes through directories and prints Avi files to textbox
public FileList()
{
InitializeComponent();
//Sets Drive Choices
DriveInfo[] drives = DriveInfo.GetDrives();
foreach (DriveInfo d in drives)
{
driveChoice.Items.Add(d);
}
}
//Find Video Files
private void btnStart_Click(object sender, EventArgs e)
{
String path = driveChoice.Text;
if (path != "C:\\")
{
String[] allfiles = Directory.GetFiles(path, "*.avi*", System.IO.SearchOption.AllDirectories);
foreach (String file in allfiles)
{
tbFileList.Text = tbFileList.Text + file + "\r\n";
}
}
else
{
Application.Exit();
}
}
}
When ran I get an error.
Unauthorized Access 'I:\$RECYCLE.BIN\S-1-5-21-1332477098-3306142970-3529014387-1000\'
Can I set the program to just skip 'I:\$RECYCLE.BIN'
Looks like you need to switch to a recursive solution or some other loop rather than using 'AllDirectories'. That way you can provide some skip logic.
see this link http://support.microsoft.com/kb/303974
and this code snippet from that page:
void DirSearch(string sDir)
{
try
{
foreach (string d in Directory.GetDirectories(sDir))
{
foreach (string f in Directory.GetFiles(d, txtFile.Text))
{
lstFilesFound.Items.Add(f);
}
DirSearch(d);
}
}
catch (System.Exception excpt)
{
Console.WriteLine(excpt.Message);
}
}
In that code you would just check your sDir for the values you want to skip.
Now there is no way to have the AllDirectories option skip specific directories or ignore exceptions that occur from traversing. You will need to manually search the directory structure and deal with errors that occur
if !filePath.Contains("I:\$RECYCLE.BIN")
Use a lambda statement to exclude the system directories:
public FileList()
{
InitializeComponent();
//Sets Drive Choices
DriveInfo[] drives = DriveInfo.GetDrives();
foreach (DriveInfo d in drives)
{
driveChoice.Items.Add(d);
}
}
//Find Video Files
private void btnStart_Click(object sender, EventArgs e)
{
String path = driveChoice.Text;
if (path != "C:\\")
{
DirectoryInfo root = new DirectoryInfo(path);
var rootFiles = root.GetFiles("*.avi");
var rootDirs = root.GetDirectories("*", SearchOption.TopDirectoryOnly).Where(d => !d.Name.Equals("System Volume Information") && !d.Name.Equals("$RECYCLE.BIN"));
foreach (var file in rootFiles)
{
tbFileList.Text = tbFileList.Text + file.FullName + "\r\n";
}
foreach (var dir in rootDirs)
{
foreach (var dirFile in dir.GetFiles("*.avi", SearchOption.AllDirectories))
{
tbFileList.Text = tbFileList.Text + dirFile.FullName + "\r\n";
}
}
}
else
{
Application.Exit();
}
}
I just tried the usage of the Lambda expression of excluding both folders from the returned string list in VS 2017. I observed something strange. If the lambda expression is directly added to the retrieval of the directories as in the string shown above the list still returns $RECYCLEBIN, however SVI folder is not returned. In order to make the lambda working correctly I needed to separate the 2 actions i.e:
var allDirs = rootDir.GetDirectories("*",SearchOption.TopDirectoryOnly);
var filteredDirs = allDirs.Where(d=> !d.Name.Equals("System Volume Information") && !d.Name.Equals("$RECYCLE.BIN"));
I am having a problem with reading the files and subfolders. My code reads fine for the given fixed source path, E:\\Folder\\test\\test2.
There are many folders in the test, like test2, test3, test4, etc. I want to extract the data files in the main folder, test.
For example, I want to extract the files in test, so I want to read all the files contained in the test instead of writing my code for test3, test4 and many. And I want to extract and write all the files as same source structure on another drive.
like, if the source structure is like E:\\Folder\\test\\test2 then the destination structure should be like C:\\Folder\\test\\test2
Is there any way to do this?
Here is my code,
private void dateTimePicker1_ValueChanged(object sender, EventArgs e)
{
DateTime dt = dateTimePicker1.Value;
txtSelectedDate.Text = dt.ToString("yyyyMMdd");
selectedDate = txtSelectedDate.Text;
}
private void button2_Click(object sender, EventArgs e)
{
DateTime stdate = Datetimepicker1.value;
while (stdate <= DateTime.Now)
{
txtSelectedDate.Text = stdate.ToString("yyyyMMdd");
selectedDate = txtSelectedDate.Text;
string DayBgSpot = "E:\\Folder\\test\\test2";
string DayBgSpotDestination = "E:\\Folder1";
int DT = int.Parse(txtSelectedDate.Text);
FileReader Reader = new FileReader();
FileReader Reader1 = new FileReader();
Reader.OpenDirectory(DayBgSpot);
Reader.ReadNaster();
string path = DayBgSpotDestination + "\\" + txtSelectedDate.Text + ".txt";
StreamWriter Strwriter = new StreamWriter(path);
try
{
while (Reader.iMaRecordsLeft > 0)
{
string SecName = Reader.sMaSecName;
string Symbol = Reader.sMaSecSymbol;
Symbol = prefix + Symbol;
int abc = 0;
Reader.OpenSecurityByName(Reader.sMaSecName);
if (Reader.iSeRecords > 0)
{
while (Reader.iSeRecordsLeft > 0)
{
Reader.ReadDay();
float O = Reader.dSeo;
float H = Reader.dSeh;
float L = Reader.dSel;
float C = Reader.dSec;
double V = Reader.dSeV;
double OI = Reader.dSrest;
string T = Reader.iSeTime.ToString();
string D = Reader.iSeDate.ToString();
if (int.Parse(D) == DT)
{
string a = string.Concat(SecName, ",", Symbol, ",", D, ",", T, ",", O, ",", H, ",", L, ",", C, ",", V, ",", OI);
if (SecName != "" && V != 0)
{
Strwriter.WriteLine(a);
}
}
}
}
abc++;
Reader.ReadNaster();
}
Reader.CloseDirectory();
Strwriter.Close();
Strwriter.Dispose();
}
catch
{
}
stdate = stdate.AddDays (1); // It will get next date till present
}
}
Something like
System.IO.DirectoryInfo baseFolder = new DirectoryInfo(#"c:\Folder\test\");
string destinationPath = #"e:\Folder\test\";
System.IO.DirectoryInfo[] subDirs = baseFolder.GetDirectories();
foreach (System.IO.DirectoryInfo dirInfo in subDirs)
{
string subFolder = dirInfo.Name;
System.IO.FileInfo[] fileInfos = dirInfo.GetFiles("*.txt");
foreach (System.IO.FileInfo fileInfo in fileInfos)
{
// Do something with the files
string writePath = destinationPath + subFolder + #"\" + fileInfo.Name;
// Write
}
}
If you are using .NET 4.0 this is one line:
var filepaths = Directory.GetFiles(path: #"C:\", searchPattern: "*pattern*", searchOption: SearchOption.AllDirectories);
Clearly, the root path and search pattern are not in line with the proposed sample, but my intention should clear.
I hope this helps
The output of my app is producing duplicates of filenames...and i'm not 100% sure why that is.
My app "cleans" the file name by finding the regex pattern in the filename. If there is none, it dumps it into a "normal" list and ignores it.
Here is the code i'm using to display my output: [this keeps showing me duplicates of filenames!!]
public partial class DriveRecursion_Results : Form
{
List<string> paths = new List<string>();
public DriveRecursion_Results()
{
InitializeComponent();
}
public void DriveRecursion(string retPath)
{
string pattern = (#"[~#&!%+{}]+");
Regex regEx = new Regex(pattern);
string[] fileDrive = Directory.GetFiles(retPath, "*.*", SearchOption.AllDirectories);
List<string> normal = new List<string>();
List<string> fileNameOnlyList = new List<string>();
dataGridView1.Rows.Clear();
try
{
foreach (string fileNames in fileDrive)
{
string strippedFileName = System.IO.Path.GetFileName(fileNames);
fileNameOnlyList.Add(strippedFileName);
foreach (string nameOnly in fileNameOnlyList)
{
if (regEx.IsMatch(strippedFileName))
{
//string fileNameOnly = Path.GetFileName(fileNames);
string pathOnly = Path.GetDirectoryName(fileNames);
DataGridViewRow dgr = new DataGridViewRow();
dgr.CreateCells(dataGridView1);
dgr.Cells[0].Value = pathOnly;
dgr.Cells[1].Value = nameOnly;
dataGridView1.Rows.Add(dgr);
string pathforInvalidName = System.IO.Path.Combine(System.IO.Path.GetDirectoryName(nameOnly), pathOnly);
paths.Add(pathforInvalidName);
}
else
{
normal.Add(strippedFileName);
}
}
}
}
catch (Exception e)
{
StreamWriter sw = new StreamWriter(retPath + "ErrorLog.txt");
sw.Write(e);
}
}
private void button1_Click_1(object sender, EventArgs e)
{
this.Close();
CleanNames clean = new CleanNames();
clean.Sanitizer(paths);
clean.Show();
}
Once it's done identifying which files need to be renamed, it cleans up the "dirty" names:
public partial class CleanNames : Form
{
public CleanNames()
{
InitializeComponent();
}
public void Sanitizer(List<string> paths)
{
string regPattern = (#"[~#&!%+{}]+");
string replacement = " ";
Regex regExPattern = new Regex(regPattern);
Regex regExPattern2 = new Regex(#"\s{2,}");
StreamWriter errors = new StreamWriter(#"S:\Test\Errors.txt", true);
var filesCount = new Dictionary<string, int>();
dataGridView1.Rows.Clear();
try
{
foreach (string files2 in paths)
{
string filenameOnly = System.IO.Path.GetFileName(files2);
string pathOnly = System.IO.Path.GetDirectoryName(files2);
string sanitizedFileName = regExPattern.Replace(filenameOnly, replacement);
sanitizedFileName = regExPattern2.Replace(sanitizedFileName, replacement);
string sanitized = System.IO.Path.Combine(pathOnly, sanitizedFileName);
if (!System.IO.File.Exists(sanitizedFileName))
{
DataGridViewRow clean = new DataGridViewRow();
clean.CreateCells(dataGridView1);
clean.Cells[0].Value = pathOnly;
clean.Cells[1].Value = filenameOnly;
clean.Cells[2].Value = sanitizedFileName;
dataGridView1.Rows.Add(clean);
System.IO.File.Move(files2, sanitized);
}
else
{
if (filesCount.ContainsKey(sanitizedFileName))
{
filesCount[sanitized]++;
}
else
{
filesCount.Add(sanitized, 1);
}
string newFileName = String.Format("{0}{1}{2}",
System.IO.Path.GetFileNameWithoutExtension(sanitized),
filesCount[sanitized].ToString(),
System.IO.Path.GetExtension(sanitized));
string newFilePath = System.IO.Path.Combine(System.IO.Path.GetDirectoryName(sanitized), newFileName);
newFileName = regExPattern2.Replace(newFileName, replacement);
System.IO.File.Move(files2, newFilePath);
sanitized = newFileName;
DataGridViewRow clean = new DataGridViewRow();
clean.CreateCells(dataGridView1);
clean.Cells[0].Value = pathOnly;
clean.Cells[1].Value = filenameOnly;
clean.Cells[2].Value = newFileName;
dataGridView1.Rows.Add(clean);
}
}
}
catch (Exception e)
{
errors.Write(e);
}
}
private void SanitizeFileNames_Load(object sender, EventArgs e)
{ }
private void dataGridView1_CellContentClick(object sender, DataGridViewCellEventArgs e)
{
}
private void button1_Click(object sender, EventArgs e)
{
Application.Exit();
}
What i'm trying to do here is ONLY show files that need to be renamed (not all files). I want to take those dirty filenames and clean them with my 2nd class.
Anybody know why i'm seeing multiples of the same file on the output? Anybody know how to fix this?!?!
My immediate observation is that your foreach (string nameOnly in fileNameOnlyList) loop should not be nested where it is. Your logic looks like this.
For each filename:
Add it to the list.
For *everything in the list*...
So you'll add one. Then process it. Then add another. Then process both. Then add. Then process all three. Etcetera.
Try this.
foreach (string fileNames in fileDrive)
{
string strippedFileName = System.IO.Path.GetFileName(fileNames);
fileNameOnlyList.Add(strippedFileName);
}
foreach (string strippedFileName in fileNameOnlyList)
{
if (regEx.IsMatch(strippedFileName))
// ...
}
Edit
Even better, why have two loops?
foreach (string fileNames in fileDrive)
{
string strippedFileName = System.IO.Path.GetFileName(fileNames);
fileNameOnlyList.Add(strippedFileName);
if (regEx.IsMatch(strippedFileName))
// ...
}
My first guess is that you are seeing duplicates because you have the loop over fileNameOnlyList inside the loop over fileDrive. This when you are processing second file name from fileDrive collection, you will add the first one to your data grid as well.
There are two possible ways to fix it:
- move the inner loop out of the outer loop and put it just under it
- remove the inner loop (but leave the code that is inside it) and use strippedFileName instead of nameOnly variable in the code
You search recursively through your directory structure
Directory.GetFiles(retPath, "*.*", SearchOption.AllDirectories);
but you use only the filename
System.IO.Path.GetFileName(fileNames);
So if you have the same file in nested folders, it will show up twice.