예제 #1
0
        /// <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);
                }
            }
        }