How to find a missing file from a directory - c#

I have a directory in which 'wav' files are stored. These files's names are sequential in order ie 1.wav, 2.wav, 3.wav.... etc.
I have to find out the missing wav file, like if 3.wav is missing then I have to find out that and the name '3' should given to a variable.
How can I do this?

You could use a simple loop and assign the variable to the loop counter and use File.Exists:
List<yourType> missingFiles = new List<yourType>();
string path;
for (var i = 0; i<length; i++) {
path = "path\" + i + ".wav";
if (!File.Exists(path) {
missingFiles.Add(path);
}
}
http://msdn.microsoft.com/en-us/library/system.io.file.exists.aspx

Related

Batch takes a part from the file name and create a folders with this part

I have files with names like this:
414_gtmlk_videos_Mas_147852_hty1147.xls
414_gtmlk_videos_Mas_P147852_hty1147.txt
I want to creat a job to check the filenames and take the part after Mas in the file name (147852-P147852)
and create a folders with this part name (the folder name should be: 147852-P147852).
And finally move each file to his folder.
Batch takes a part from the file name and create a folders with this part i have files with names like this:
414_gtmlk_videos_Mas_147852_hty1147.xls
414_gtmlk_videos_Mas_P147852_hty1147.txt (the folder name will be
here:147852-P147852)
Here's a way to do this with a Batch Script since you have this tagged as a batch-file in your question. Just set your source directory accordingly and the rest should just work based on the detail you provided and my understanding.
I used a simple batch FOR /F loop incorporating MD with IF conditions. I used the underbar characters as the delimiter and set the token to 5 to make this work.
#ECHO ON
SET Src=C:\Folder\Path
FOR /F "TOKENS=5 DELIMS=_" %%F IN ('DIR /B /A-D "%Src%\*.txt"') DO (
IF NOT EXIST "%Src%\%%~F-P%%~F" MD "%Src%\%%~F-P%%~F"
IF EXIST "%Src%\*%%~F*P%%~F*.txt" MOVE /Y "%Src%\*%%~F*P%%~F*.txt" "%Src%\%%~F-P%%~F"
)
GOTO EOF
Further Resources
FOR /F
IF
MD
FOR /?
delims=xxx - specifies a delimiter set. This replaces the
default delimiter set of space and tab.
tokens=x,y,m-n - specifies which tokens from each line are to
be passed to the for body for each iteration.
This will cause additional variable names to
be allocated. The m-n form is a range,
specifying the mth through the nth tokens. If
the last character in the tokens= string is an
asterisk, then an additional variable is
allocated and receives the remaining text on
the line after the last token parsed.
I have some C# code below. The first part does the following:
Gets paths
Get names of file
Modify full paths to get "147852" part, between __Mas_ and last _
string pathToGetFile = #"C:\\";
string[] filePaths = System.IO.Directory.GetFiles(pathToGetFile +#"\\", "*_Mas_*");
string[] fullName = new string[filePaths.Length];
for (int i = 0; i < filePaths.Length; i++)
{
fullName[i] = filePaths[i].Substring(filePaths[i].LastIndexOf("\\") + 1);
filePaths[i] = filePaths[i].Substring(filePaths[i].LastIndexOf("_Mas_") + 5);
int l = filePaths[i].IndexOf("_");
filePaths[i] = filePaths[i].Substring(0, l);
Now you can create folders with yours names
filePaths is now like that: 147852, P147852
if (!Directory.Exists(#"C:\" + filePaths[i]))
System.IO.Directory.CreateDirectory(#"C:\" + filePaths[i]);
}
Now just move files to new directories
for (int i = 0; i < filePaths.Length; i++)
{
string sourceFile = System.IO.Path.Combine(pathToGetFile, fullName[i]);
string destFile = System.IO.Path.Combine(#"C:\" + filePaths[i], #"C:\" + filePaths[i] + "\\" + fullName[i]);
File.Copy(sourceFile,destFile,true);
}
Now, what happens
Files:
C:\414_gtmlk_videos_Mas_147852_hty1147.xls
C:\414_gtmlk_videos_Mas_P147852_hty1147.txt
They will be copied according to the:
C:\147852\
C:\P147852\

Renaming files programmatically, decrementing

I have a folder with a certain number of text files named 1.txt, 2.txt 3.txt etc.
My goal is that when one of them is deleted, to rename any of the files greater than the file deleted down one.
Ex. if 1.txt is deleted, 2 should be renamed to 1, and 3 renamed to 2, so on and so forth.
Here is my attempt so far:
private void deletequestionbtn_Click(object sender, EventArgs e)
{
string fileDel = testfolderdialog.SelectedPath.ToString() + #"\" + questionCountint.ToString() + ".txt";
DirectoryInfo d = new DirectoryInfo(testfolderdialog.SelectedPath.ToString() + #"\");
File.Delete(fileDel);
questionCountint++;
foreach (var file in d.GetFiles("*.txt"))
{
string fn = file.Name;
string use = fn.Replace(".txt", "");
int count = int.Parse(use);
if (count > questionCountint)
{
File.Move(fileDel, testfolderdialog.SelectedPath.ToString() + #"\" + questionCountint--.ToString() + ".txt");
}
}
}
The issue is occuring on the File.Move line, it's saying it cannot locate the file in fileDel, though I am incrementing questionCountint after deleting fileDel
Am I approaching this the wrong way? Is there a more effective way to write the foreach statement? I only want to rename the files greater than the file deleted.
Where am I going wrong?
The problem is that you are trying to rename fileDel, which is the file that you have deleted. You should rename file instead.
However, you will quickly run into the next problem. If you don't get the files in the exact order that you expect, you will try to rename a file to a name that already exists.
If the GetFiles method returns the files in the order "3.txt", "2.txt", you will first try to rename "3.txt" to "2.txt", but "2.txt" already exists.
You should first loop through the files and gather all files that should be renamed. Then you should sort the files on the number so that you can rename them in the correct order.
As the format of the file names is so simple to recreate from the number, you can just get the numbers in a list:
List<int> files = new List<int>();
foreach (var file in d.GetFiles("*.txt")) {
string fn = file.Name;
string use = fn.Replace(".txt", "");
int count = int.Parse(use);
if (count > questionCountint) {
files.Add(count);
}
}
string path = testfolderdialog.SelectedPath.ToString();
foreach (int count in files.Ordery(n => n)) {
File.Move(String.Concat(path, count.ToString() + ".txt"), String.Concat(path, (count - 1).ToString() + ".txt");
}

Compare file name variable with file path variable

I have created some code which pulls a list of file names off the server and stores them, I also get the folder names from a directory on my computer and I need to compare them both to find out if there are any names which are on the local machine and not on the server.
serverlistarray contains the list of folders on the server (1 folder per entry), local listarray contains the directory listing on the local computer, this is also has 1 folder per entry. I read the local files using this:
String[] localfilelistarray = System.IO.Directory.GetDirectories(/*file location*/);
My problem lies within the get directory's, it includes the full path of the file which I cannot compare. The code below is what I have tried to do, I check the serverlistarray for the file in locallistarray and if they match i put them in the list.
for (int b = 0; b < localfilelistarray.Length; b++)
{
//problem with the compare
if (!serverlistarray.Contains(localfilelistarray[b].Replace(/*file path before filename*/, "")))
{
//add to list variable
}
}
I then use this code to do what I want for everything in the list (for now its a message box to show the filename).
for (int f = 0; f < delete.Count(); f++)
{
MessageBox.Show(/*list variable*/);
}
BUT I get every file even if it is in the serverlistarray and I cant work out whats wrong. I believe its to do with the comparison of the two arrays but when I put message boxes in that loop thay come out as expected but the comparison doesnt seem to work.
Can anyone see what ive done wrong?
ive tried using replace and direct comparisons to no avail. I though of adding the file path to the serverlistarray BUT I can not do this as I need the raw file name for server operations and other parts of this code.
EDIT:
serverlistarray example:
[0]folder1
[1]folder2
[2]folder3
localfilearray example:
[0]c:\\users\Noliver\folder1
[1]c:\\users\Noliver\folder2
[2]c:\\users\Noliver\folder3
[3]c:\\users\Noliver\folder4
[4]c:\\users\Noliver\folder5
expected output (message boxes in for loop):
c:\\users\Noliver\folder4
&
c:\\users\Noliver\folder5
EDIT 2:
Ive tried this code with no lick using the file path:
for (int b = 0; b < localfilelistarray.Length; b++)
{
String[] temp = System.IO.Path.GetFileName(localfilelistarray[b]).Split('.');
MessageBox.Show(localfilelistarray[b] + " - " + temp[0]);
for (int t = 0; t < serverlistarray.Length;t++)
{
MessageBox.Show("server " + serverlistarray[t] + " - " + localfilelistarray[b] + " - " + temp[0]);
}
if (!update.Contains(temp[0]))
{
delete.Add(localfilelistarray[b]);
}
}
the output from this showed that the serverlistarray contained the file name from temp[0] (the file name with the extension taken off) but all the files were in the list variable. could this come down to new lines or a space at the end of one of the strings? for some reason the if statement checking if the array contains the value doesnt work.
From the way the string is stored the deepest folder name were just written as if they are a file name. So I used Path.GetFileName to extract it.
localfilearray.Where(x => !serverlistarray.Contains(Path.GetFileName(x)))
This work as well on most of case, if you don't like the name of previous one :
localfilearray.Where(x => !serverlistarray.Contains(x.Split('\\').Last()))
To use the above code with what you have now, you can :
Expand your existing delete list to include what to delete :
delete.AddRange(localfilearray.Where(x => !serverlistarray.Contains(x.Split('\\').Last())));
Or, just declare it like this :
var delete = new List(localfilearray.Where(x => !serverlistarray.Contains(x.Split('\\').Last())));`
I'd advise against splitting on "\" etc., instead use DirectoryInfo to get the name of the directory:
var directoryInfo = new DirectoryInfo(#"c:\MyDir");
String directoryName = directoryInfo.Name; // returns "MyDir"

copying files from one folder to another only if their file name is a in a specified text file c#

I need to copy files from one folder to another but only if their file name is also in a text file. The text file is set up like so
file1.jpg
file2.jpg
file3.jpg
etc
There are around one-million files to copy. I'm using C#.
What would the best way to go about this be? I'm not sure if I should first read all the file names from the text file and put them in to a list then possibly convert the list in to an array then maybe use the array somehow? Or maybe there's a better way to go about it?
I know how to read and write to files and how to copy from one source destination to another. I don't know how to filter out specific files when copying from one source destination to another though.
Any help is greatly appreciated.
Thank you.
The following code will help you the process you want
string source = #"C:\SourcePath\";
string destination = #"C:\DestinationPath\";
string[] strFiles = File.ReadAllText(#"C:\Filename.txt").Split(' ');
for (int i = 0; i < strFiles.Length; i++)
{
File.Copy(source + strFiles[i], destination + strFiles[i]);
}
If the text file is one line with million files name. Use this
string from = #"c:\from" , to =#"d:\to"; // source and destination
StreamReader file = new StreamReader(#"c:\list.txt"); // your files list
string total=file.ReadLine();
string[] tobecopied = total.Split(' ');
foreach(string fil in tobecopied)
{
if(File.Exists(from+#"\"+fil))
{
File.Copy(from+#"\"+fil,to+#"\"+fil);
}
else
{
MessageBox.Show(fil+"Not found ");
}
}
But if the text file have 1 line per 1 file , for example
FIle1.exe
File2.exe
use this
string from = #"c:\from" , to =#"d:\to"; // source and destination
StreamReader file = new StreamReader(#"c:\list.txt"); // your files list
string total="";
string temp="";
while((temp=file.ReadLine())!=null)
{
total+=temp+" ";
}
string[] tobecopied = total.Split(' ');
foreach(string fil in tobecopied)
{
if(File.Exists(from+#"\"+fil))
{
File.Copy(from+#"\"+fil,to+#"\"+fil);
}
else
{
MessageBox.Show(fil+"Not found ");
}
}
These ways also check for file existance.
Hope it works. If someone see error please edit it.

Get files from folders to list, add subdirectories to dropdown and list filenames on list

Have a look at this screenshot first to see what happens:
What you can see on this screenshot is what I have done already.. But I want to add a few things more.
Right now by clicking at the "Add to list" button all files with their full path are stored in List A. Their file names are stored in List B. And heres the code for it:
if (type == "folder")
{
string listPath = this.configsPath.Text;
string[] filesToList = System.IO.Directory.GetFiles(listPath, "*.*", System.IO.SearchOption.AllDirectories);
foreach (string file in filesToList)
{
if (!configsChkList.Items.Contains(file))
{
configsChkList.Items.Add(file, false);
configsDestList.Items.Add(Path.GetFileName(file));
}
}
}
I want List b to also store their path relative to the path specified in the input field.. The last three entries in List A as an example are in a sub-directory called "undermappe", but since I use Path.GetFileName to store the entries in List B the sub-directory does not get viewed.. How can I do this?
And then another thing. The sub-directories should also be stored in the ComboBox on top, but only the directories not the names! How can I do this ?
I didn't write this (so I won't take credit), but this function returns the relative path:
/// <summary>
/// method to provide a relative path from a directory to a path
/// </summary>
/// <param name="fromDirectory">the starting folder</param>
/// <param name="toPath">the path that will be pointed to</param>
/// <returns>string</returns>
public static string RelativePathTo(string fromDirectory, string toPath)
{
if (fromDirectory == null)
{
throw new ArgumentNullException("fromDirectory");
}
if (toPath == null)
{
throw new ArgumentNullException("fromDirectory");
}
if (System.IO.Path.IsPathRooted(fromDirectory) && System.IO.Path.IsPathRooted(toPath))
{
if (string.Compare(System.IO.Path.GetPathRoot(fromDirectory)
, System.IO.Path.GetPathRoot(toPath), true) != 0)
{
throw new ArgumentException(
String.Format("The paths '{0} and '{1}' have different path roots."
, fromDirectory
, toPath));
}
}
StringCollection relativePath = new StringCollection();
string[] fromDirectories = fromDirectory.Split(System.IO.Path.DirectorySeparatorChar);
string[] toDirectories = toPath.Split(System.IO.Path.DirectorySeparatorChar);
int length = Math.Min(fromDirectories.Length, toDirectories.Length);
int lastCommonRoot = -1;
// find common root
for (int x = 0; x < length; x++)
{
if (string.Compare(fromDirectories[x], toDirectories[x], true) != 0)
{
break;
}
lastCommonRoot = x;
}
if (lastCommonRoot == -1)
{
throw new ArgumentException(
string.Format("The paths '{0} and '{1}' do not have a common prefix path."
, fromDirectory
, toPath));
}
// add relative folders in from path
for (int x = lastCommonRoot + 1; x < fromDirectories.Length; x++)
{
if (fromDirectories[x].Length > 0)
{
relativePath.Add("..");
}
}
// add to folders to path
for (int x = lastCommonRoot + 1; x < toDirectories.Length; x++)
{
relativePath.Add(toDirectories[x]);
}
// create relative path
string[] relativeParts = new string[relativePath.Count];
relativePath.CopyTo(relativeParts, 0);
string newPath = string.Join(System.IO.Path.DirectorySeparatorChar.ToString(), relativeParts);
return newPath;
}
I'm sorry but I don't understand your second request, but if you are asking how to get the name of a directory it is quite easy with DirectoryInfo
DirectoryInfo di = new DirectoryInfo(#"c\temp\en");
string s = di.Name;
I want List b to also store their path relative to the path specified in the input field.. The last three entries in List A as an example are in a sub-directory called "undermappe", but since I use Path.GetFileName to store the entries in List B the sub-directory does not get viewed.. How can I do this?
Just remove the first X characters where X is the Length of the path in the input field. This can be done with Substring(); something like:
string relativePath = stringFromListBox.Substring(stringFromInputField.Length + 1);
The "+ 1" should get rid of the leading slash.
For the second part of your question, about the paths in the combo box, you can take each full file name, and use Path.GetDirectoryName() to get just the directory.
var files = new []{#"f:\Noter\Test\2004 ABC Musik.txt",#"f:\Noter\Test\activision_support.txt",#"f:\Noter\Test\Alberte.txt",#"F:\Noter\Test\undermappe\steam password!.txt"};
var folders = files.Select(f => System.IO.Path.GetDirectoryName(f)).Distinct().ToList();
If you want just the folders under the main 'F:\noter\test' folder, then just use your relative path code on them from answers for the first part of your question
**Hi.
try this example , i think this is what you need , 100% working:**
System.String basefolder = "NASSIM\\LOUCHANI\\";
foreach (String file in Directory.GetFiles(basefolder,"*.*"))
{
comboBox1.Items.Add(Path.GetFileNameWithoutExtension(file));
//Load file name without extension / path.
}

Categories