public void RelativePaths() { // Note: since this test runs for netcoreapp3.1 and netstandard2.0 it effectively // ensures consistent behaviour between my implementation and the the .net core one. string rel; rel = Path_.RelativePath(@"A:\aaa\eee\fff\", @"A:\aaa\BBB\ccc\ddd"); Assert.Equal(rel, @"..\..\BBB\ccc\ddd"); rel = Path_.RelativePath(@"A:\aaa\eee\fff\", @"A:\aaa\bbb\..\..\ddd"); Assert.Equal(rel, @"..\..\..\ddd"); rel = Path_.RelativePath(@"A:\aaa\eee\fff\", @"B:\AAA\BBB\CCC\DDD"); Assert.Equal(rel, @"B:\AAA\BBB\CCC\DDD"); rel = Path_.RelativePath(@"A:\aaa\eee\fff", @"A:\aaa\"); Assert.Equal(rel, @"..\.."); rel = Path_.RelativePath(@"A:\aAa\eee\fff", @"A:\AaA\BbB\"); Assert.Equal(rel, @"..\..\BbB\"); rel = Path_.RelativePath(@"A:\aAa", @"A:\AaA\BbB\CcC"); Assert.Equal(rel, @"BbB\CcC"); rel = Path_.RelativePath(@"A:\aAa\Part", @"A:\AaA\Partial\CcC"); Assert.Equal(rel, @"..\Partial\CcC"); }
// Example Use: // <TextBlock> // <TextBlock.Text> // <MultiBinding Converter="{conv:RelativePath}"> // <Binding Path="FullPath" /> // <Binding Path="BasePath" /> // </MultiBinding> // </TextBlock.Text> // </TextBlock> public object?Convert(object[] values, Type targetType, object parameter, CultureInfo culture) { if (!(values[0] is string full_path)) { return(null); } if (!(values[1] is string base_path)) { return(null); } return(Path_.RelativePath(base_path, full_path)); }
/// <summary> /// Smart copy from 'src' to 'dst'. Loosely like XCopy. /// 'src' can be a single file, a comma separated list of files, or a directory<para/> /// 'dst' can be a /// if 'src' is a directory, </summary> public static void Copy(string src, string dst, bool overwrite = false, bool only_if_modified = false, bool ignore_non_existing = false, Action <string>?feedback = null, bool show_unchanged = false) { var src_is_dir = Path_.IsDirectory(src); var dst_is_dir = Path_.IsDirectory(dst) || dst.EndsWith("/") || dst.EndsWith("\\") || src_is_dir; // Find the names of the source files to copy var files = new List <string>(); if (src_is_dir) { files = Path_.EnumFileSystem(src, SearchOption.AllDirectories).Select(x => x.FullName).ToList(); } else if (Path_.FileExists(src)) { files = new List <string>() { src } } ; else if (src.Contains('*') || src.Contains('?')) { files = Path_.EnumFileSystem(src, SearchOption.AllDirectories, new Pattern(EPattern.Wildcard, src).RegexString).Select(x => x.FullName).ToList(); } else if (!ignore_non_existing) { throw new FileNotFoundException($"'{src}' does not exist"); } // If the 'src' represents multiple files, 'dst' must be a directory if (src_is_dir || files.Count > 1) { // if 'dst' doesn't exist, assume it's a directory if (!Path_.DirExists(dst)) { dst_is_dir = true; } // or if it does exist, check that it is actually a directory else if (!dst_is_dir) { throw new FileNotFoundException($"'{dst}' is not a valid directory"); } } // Ensure that 'dstdir' exists. (Canonicalise fixes the case where 'dst' is a drive, e.g. 'C:\') var dstdir = Path_.Canonicalise((dst_is_dir ? dst : Path_.Directory(dst)).TrimEnd('/', '\\')); if (!Path_.DirExists(dstdir)) { Directory.CreateDirectory(dstdir); } // Copy the file(s) to 'dst' foreach (var srcfile in files) { // If 'dst' is a directory, use the same filename from 'srcfile' var dstfile = string.Empty; if (dst_is_dir) { var spath = src_is_dir ? Path_.RelativePath(src, srcfile) : Path_.FileName(srcfile); dstfile = Path_.CombinePath(dstdir, spath); } else { dstfile = dst; } // If 'srcfile' is a directory, ensure the directory exists at the destination if (Path_.IsDirectory(srcfile)) { if (!dst_is_dir) { throw new Exception($"ERROR: {dst} is not a directory"); } // Create the directory at the destination if (!Path_.DirExists(dstfile)) { System.IO.Directory.CreateDirectory(dstfile); } if (feedback != null) { feedback(srcfile + " --> " + dstfile); } } else { // Copy if modified or always based on the flag if (only_if_modified && !Path_.DiffContent(srcfile, dstfile)) { if (feedback != null && show_unchanged) { feedback(srcfile + " --> unchanged"); } continue; } // Ensure the directory path exists var d = Path_.Directory(dstfile); var f = Path_.FileName(dstfile); if (!Path_.DirExists(d)) { System.IO.Directory.CreateDirectory(d); } if (feedback != null) { feedback(srcfile + " --> " + dstfile); } File.Copy(srcfile, dstfile, overwrite); } } }