How to get double quotes around folder names with spaces - c#

Here is my code
string path1 = #"C:\Program Files (x86)\Common Files";
string path2 = #"Microsoft Shared";
string path = Path.Combine(path1, path2);
Console.WriteLine(path);
The output provides me
C:\Program Files (x86)\Common Files\Microsoft Shared
I would like to have any folder names with spaces in double quotes as follows
C:\"Program Files (x86)"\"Common Files"\"Microsoft Shared"
How can I get that?

The easiest way to do this would be with LINQ.
You can split your folder path into an array listing all of the folder names, then manipulate each individual element using a Select().
In your case you would want to:
Split the string into an array (using the '/' to separate elements)
Format the folder name as "{folderName}" if the folder name contains spaces
Rejoin the array as a single string, with the '/' for your delimiter
Here is what that would look like, please note I have used 2 Select()'s for clarity & to help identify the different steps. They can be a single statement.
string path1 = #"C:\Program Files (x86)\Common Files";
string path2 = #"Microsoft Shared";
string path = System.IO.Path.Combine(path1, path2);
var folderNames = path.Split('\\');
folderNames = folderNames.Select(fn => (fn.Contains(' ')) ? String.Format("\"{0}\"", fn) : fn)
.ToArray();
var fullPathWithQuotes = String.Join("\\", folderNames);
The output of the above process is:
C:\"Program Files (x86)"\"Common Files"\"Microsoft Shared"

You can create an extension method
public static class Ex
{
public static string PathForBatchFile(this string input)
{
return input.Contains(" ") ? $"\"{input}\"" : input;
}
}
use it like
var path = #"C:\Program Files (x86)\Common Files\Microsoft Shared";
Console.WriteLine(path.PathForBatchFile());
It uses the string interpolation feature in C# 6.0. If you are not using C# 6.0 you can use this instead.
public static class Ex
{
public static string PathForBatchFile(this string input)
{
return input.Contains(" ") ? string.Format("\"{0}\"", input) : input;
}
}

Related

How to create a folder out of the first few letters of a filename?

So I checked out the basic things but I'd like to do the following:
I have 5 files let's say: X1_word_date.pdf, XX1_word_date.pdf, etc...
I'd like to create a folder structure like: C:\PATH\X1, C:\PATH\XX1, etc...
So how do I take the first letters before the '_' in the file names and put it into a string?
My idea is that I use the Directory.CreateDirectory and than combine the main path and the strings so I get the folders.
How do I do that? Help appreciated.
string fileName = "X1_word_date.pdf";
string[] tokens = fileName.Split('_');
string myPath = "C:\\PATH\\";
Directory.CreateDirectory( myPath + tokens[0]);
Something like this should work. Using Split() will also allow for numbers greater than 9 to be dealt with
Supposed that your files is a List<string> which contains the file name (X2_word_date.pdf,...)
files.ForEach(f => {
var pathName= f.Split('_').FirstOrDefault();
if(!string.IsNullOrEmpty(pathName))
{
var directoryInfo = DirectoryInfo(Path.Combine(#"C:\PATH", pathName));
if(!directoryInfo.Exists)
directoryInfo.Create();
//Then move this current file to the directory created, by FileInfo and Move method
}
})
With simple string methods like Split and the System.IO.Path class:
var filesAndFolders = files
.Select(fn => new
{
File = fn,
Dir = Path.Combine(#"C:\PATH", Path.GetFileNameWithoutExtension(fn).Split('_')[0].Trim())
});
If you want to create that folder and add the file:
foreach (var x in filesAndFolders)
{
Directory.CreateDirectory(x.Dir); // will only create it if it doesn't exist yet
string newFileName = Path.Combine(x.Dir, x.File);
// we don't know the old path of the file so i can't show how to move
}
Or using regex
string mainPath = #"C:\PATH";
string[] filenames = new string[] { "X1_word_date.pdf", "X2_word_date.pdf" };
foreach (string filename in filenames)
{
Match foldernameMatch = Regex.Match(filename, "^[^_]+");
if (foldernameMatch.Success)
Directory.CreateDirectory(Path.Combine(mainPath, foldernameMatch.Value));
}
Using the bigger picture starting with only your Source and Destination directory.
We can list all files we need to move with Directory.GetFiles.
In this list We first isolate the filename with GetFileName.
Using simple String.Split you have the new directory name.
Directory.CreateDirectory will create directories unless they already exist.
To move the file we need its destination path, a combinaison of the Destination directory path and the fileName.
string sourceDirectory = #"";
string destDirectory = #"";
string[] filesToMove = Directory.GetFiles(sourceDirectory);
foreach (var filePath in filesToMove) {
var fileName = Path.GetFileName(filePath);
var dirPath = Path.Combine(destDirectory, fileName.Split('_')[0]);
var fileNewPath= Path.Combine(dirPath,fileName);
Directory.CreateDirectory(dirPath);// If it exist it does nothing.
File.Move(filePath, fileNewPath);
}

How do I remove middle characters in a file name for each file in a directory

How do I remove characters in the middle of each file name in a directory?
My directory is filled with files like: "Example01.1234312232.txt", "Example02.2348234324.txt", etc.
I would like to remove the ".1234312232" so it will named "Example01.txt", and do this for every file in the directory.
Each file name will always have the same number of characters in it.
You could use
string fileNameOnly = Path.GetFileNameWithoutExtension(path);
string newFileName = string.Format("{0}{1}",
fileNameOnly.Split('.')[0],
Path.GetExtension(path));
Demo
For what it's worth, the complete code for your directory-renaming problem:
foreach (string file in Directory.GetFiles(folder))
{
string fileNameOnly = Path.GetFileNameWithoutExtension(file);
string newFileName = string.Format("{0}{1}",
fileNameOnly.Split('.')[0],
Path.GetExtension(file));
File.Move(file, Path.Combine(folder, newFileName));
}
The simplest way would be to use a regular expression replacement of
\.\d+
for an empty string "":
var str = "Example01.1234312232.txt";
var res = Regex.Replace(str, #"\.\d+", "");
Console.WriteLine("'{0}'", res);
Here is a link to a demo on ideone.
You'll have to use the IO.DirectoryInfo class and the GetFiles function to get the list of files.
Loop all files and do a substring to get the string you want.
Then you call My.Computer.Filesystem.RenameFile to rename the files.
Use this:
filename.Replace(filename.Substring(9, 15), ".txt")
You can hard code the index and length because you said the number of characters have same length.
Use Directory.EnumerateFiles to enumerate the files, Regex.Replace to get the new name and File.Move to rename files:
using System.IO;
using System.Text.RegularExpressions;
class SampleSolution
{
public static void Main()
{
var path = #"C:\YourDirectory";
foreach (string fileName in Directory.EnumerateFiles(path))
{
string changedName = Regex.Replace(fileName, #"\.\d+", string.Empty);
if (fileName != changedName)
{
File.Move(fileName, changedName);
}
}
}
}

Matching subdirectory by comparing part of the directory path

I probably didn't word the title too well but hopefully my explanation should illustrate the problem.
Basically, I have to find out the names of the subdirectories excluding the file name when given another path to compare with. For instance,
Given: "C:\Windows\System32\catroot\sys.dll"
Compare: "C:\Windows"
Matched String: "\System32\catroot"
Here's another example:
Given: "C:\Windows\System32\WindowsPowerShell\v1.0\Examples\profile.ps1"
Compare: "C:\Windows\System32"
Matched String: "\WindowsPowerShell\v1.0\Examples"
What would be the best way to perform this matching?
You might also want to consider special cases such as:
Relative paths
Paths with short names such as C:\PROGRA~1 for C:\Program Files
Non-canonical paths (C:\Windows\System32\..\..\file.dat)
Paths that use an alternate separator (/ instead of \)
One way is to convert to a canonical full path using Path.GetFullPath before comparing
E.g.
string toMatch = #"C:\PROGRA~1/";
string path1 = #"C:/Program Files\Common Files\..\file.dat";
string path2 = #"C:\Program Files\Common Files\..\..\file.dat";
string toMatchFullPath = Path.GetFullPath(toMatch);
string fullPath1 = Path.GetFullPath(path1);
string fullPath2 = Path.GetFullPath(path2);
// fullPath1 = C:\Program Files\file.dat
// toMatchFullPath = C:\Program Files\
if (fullPath1.StartsWith(toMatchFullPath, StringComparison.OrdinalIgnoreCase))
{
// path1 matches after conversion to full path
}
// fullPath2 = C:\file.dat
// toMatchFullPath = C:\Program Files\
if (fullPath2.StartsWith(toMatchFullPath, StringComparison.OrdinalIgnoreCase))
{
// path2 does not match after conversion to full path
}
There is no need to use Regex.
This could be easily done using string.StartsWith, string.Substring and Path.GetDirectoryName to remove the filename.
string fullPath = #"C:\Windows\System32\WindowsPowerShell\v1.0\Examples\profile.ps1";
string toMatch = #"C:\Windows\System32";
string result = string.Empty;
if(fullPath.StartsWith(toMatch, StringComparison.CurrentCultureIgnoreCase) == true)
{
result = Path.GetDirectoryName(fullPath.Substring(toMatch.Length));
}
Console.WriteLine(result);
EDIT: this changes take care of the observation from aiodintsov and include the idea from #Joe about non-canonical or partial path names
string fullPath = #"C:\Windows\System32\WindowsPowerShell\v1.0\Examples\profile.ps1";
string toMatch = #"C:\Win";
string result = string.Empty;
string temp = Path.GetDirectoryName(Path.GetFullPath(fullPath));
string[] p1 = temp.Split('\\');
string[] p2 = Path.GetFullPath(toMatch).Split('\\');
for(int x = 0; x < p1.Length; x++)
{
if(x >= p2.Length || p1[x] != p2[x])
result = string.Concat(result, "\\", p1[x]);
}
In this case I assume that the partial match should be considered as no match.
Also take a look at the answer from #Joe for the problem of partial or non-canonical paths

In C# how can I prepare a string to be valid for windows directory name

I am writing a C# program which reads certain tags from files and based on tag values it creates a directory structure.
Now there could be anything in those tags,
If the tag name is not suitable for a directory name I have to prepare it to make it suitable by replacing those characters with anything suitable. So that directory creation does not fail.
I was using following code but I realised this is not enough..
path = path.replace("/","-");
path = path.replace("\\","-");
please advise what's the best way to do it..
thanks,
Import System.IO namespace and for path use
Path.GetInvalidPathChars
and for filename use
Path.GetInvalidFileNameChars
For Eg
string filename = "salmnas dlajhdla kjha;dmas'lkasn";
foreach (char c in Path.GetInvalidFileNameChars())
filename = filename.Replace(System.Char.ToString(c), "");
foreach (char c in Path.GetInvalidPathChars())
filename = filename.Replace(System.Char.ToString(c), "");
Then u can use Path.Combine to add tags to create a path
string mypath = Path.Combine(#"C:\", "First_Tag", "Second_Tag");
//return C:\First_Tag\Second_Tag
You can use the full list of invalid characters here to handle the replacement as desired. These are available directly via the Path.GetInvalidFileNameChars and Path.GetInvalidPathChars methods.
The characters you must now use are: ? < > | : \ / * "
string PathFix(string path)
{
List<string> _forbiddenChars = new List<string>();
_forbiddenChars.Add("?");
_forbiddenChars.Add("<");
_forbiddenChars.Add(">");
_forbiddenChars.Add(":");
_forbiddenChars.Add("|");
_forbiddenChars.Add("\\");
_forbiddenChars.Add("/");
_forbiddenChars.Add("*");
_forbiddenChars.Add("\"");
for (int i = 0; i < _forbiddenChars.Count; i++)
{
path = path.Replace(_forbiddenChars[i], "");
}
return path;
}
Tip: You can't include double-quote ("), but you can include 2 quotes ('').
In this case:
string PathFix(string path)
{
List<string> _forbiddenChars = new List<string>();
_forbiddenChars.Add("?");
_forbiddenChars.Add("<");
_forbiddenChars.Add(">");
_forbiddenChars.Add(":");
_forbiddenChars.Add("|");
_forbiddenChars.Add("\\");
_forbiddenChars.Add("/");
_forbiddenChars.Add("*");
//_forbiddenChars.Add("\""); Do not delete the double-quote character, so we could replace it with 2 quotes (before the return).
for (int i = 0; i < _forbiddenChars.Count; i++)
{
path = path.Replace(_forbiddenChars[i], "");
}
path = path.Replace("\"", "''"); //Replacement here
return path;
}
You'll of course use only one of those (or combine them to one function with a bool parameter for replacing the quote, if needed)
The correct answer of Nikhil Agrawal has some syntax errors.
Just for the reference, here is a compiling version:
public static string MakeValidFolderNameSimple(string folderName)
{
if (string.IsNullOrEmpty(folderName)) return folderName;
foreach (var c in System.IO.Path.GetInvalidFileNameChars())
folderName = folderName.Replace(c.ToString(), string.Empty);
foreach (var c in System.IO.Path.GetInvalidPathChars())
folderName = folderName.Replace(c.ToString(), string.Empty);
return folderName;
}

How to find the file by its partial name?

How can I get the full filename?
For example:
I have a file named 171_s.jpg that is stored on the hard disc.
I need to find the file by its partial name, i.e. 171_s, and get the full name.
How can I implement this?
Here's an example using GetFiles():
static void Main(string[] args)
{
string partialName = "171_s";
DirectoryInfo hdDirectoryInWhichToSearch = new DirectoryInfo(#"c:\");
FileInfo[] filesInDir = hdDirectoryInWhichToSearch.GetFiles("*" + partialName + "*.*");
foreach (FileInfo foundFile in filesInDir)
{
string fullName = foundFile.FullName;
Console.WriteLine(fullName);
}
}
Update - Jakub answer is more efficient way to do.
ie, use System.IO.Directory.GetFiles()
http://msdn.microsoft.com/en-us/library/ms143316.aspx
The answer has been already posted, however for an easy understanding here is the code
string folderPath = #"C:/Temp/";
DirectoryInfo dir= new DirectoryInfo(folderPath);
FileInfo[] files = dir.GetFiles("171_s*", SearchOption.TopDirectoryOnly);
foreach (var item in files)
{
// do something here
}
You could use System.IO.Directory.GetFiles()
http://msdn.microsoft.com/en-us/library/ms143316.aspx
public static string[] GetFiles(
string path,
string searchPattern,
SearchOption searchOption
)
path
Type: System.String
The directory to search.
searchPattern
Type: System.String
The search string to match against the names of files in path. The parameter cannot end in two periods ("..") or contain two periods
("..") followed by DirectorySeparatorChar or
AltDirectorySeparatorChar, nor can it contain any of the characters in
InvalidPathChars.
searchOption
Type: System.IO.SearchOption
One of the SearchOption values that specifies whether the search operation should include all subdirectories or only the current
directory.
You can do it like this:
....
List<string> _filesNames;
foreach(var file in _directory)
{
string name = GetFileName(file);
if(name.IndexOf(_partialFileName) > 0)
{
_fileNames.Add(name);
}
}
....
Simple as that:
string path = #"C:\example\directory";
string searchPattern = "*171_s*";
string[] filePaths = Directory.GetFiles(path, searchPattern,SearchOption.AllDirectories);

Categories

Resources