吾爱破解 - LCG - LSG |安卓破解|病毒分析|www.52pojie.cn

 找回密码
 注册[Register]

QQ登录

只需一步,快速开始

查看: 2404|回复: 27
收起左侧

[其他原创] 批处理和C# 搜索文件和目录,复制文件和目录源代码,改天加个界面

  [复制链接]
Cool_Breeze 发表于 2021-5-28 12:54
本帖最后由 Cool_Breeze 于 2021-5-29 17:42 编辑

我在别处一个论坛上面回答一个网友的问题!个人感觉不错!在此分享给大家!

以下是问题描述:

现有:file.txt一个,里面有1000多个换行的文件名(有些有后缀,有些没,有些是文件夹)

根据这个txt里面列出来的文件名,到另一个文件夹a里(含下面所有级别的子文件夹)去依次检索文件名或文件夹名。

检索出来的文件/文件夹按照a文件夹下面的原有路径放到(复制)另一个指定文件夹b,注意b现在还是个空文件夹。

未找到的文件名输出到另一个"未找到.txt"文件里。

示例:

file.txt里面内容:
0007cebt
a400cebt
千岛湖3月拍摄.jpg
2016-5-7


需要进行的操作:
找到:a\ccbbt\2017\vae\0007cebt.pdf
放到:b\ccbbt\2017\vae\里面

未找到:a400cebt
将内容 "a400cebt" 写入"未找到.txt"里面

找到:a\照片\千岛湖3月拍摄.jpg
放到:b\照片\里面

找到:a\2016\2016-5-7(文件夹)
整个文件夹放到:b\2016里面

最后询问是否删除所有原路径下已经被复制的文件和文件夹


脚本文件必须要放在源目录盘符下。

批处理源代码
[Bash shell] 纯文本查看 复制代码
@echo off
title By Author GIN 2021/05/25
SETLOCAL ENABLEDELAYEDEXPANSION

set souceFile=files.txt
set targetDir=d:\gin\c#
set notFoundFileName=未找到.txt

set newDirectory=%cd%\newDirectory
if not exist %newDirectory% (md "%newDirectory%")
REM 源路径为:d:\gin\c#
REM 新路径为:D:\GIN\copyFile\newDirectory
echo 源路径为:%targetDir%
echo 新路径为:%newDirectory%

call :equalTotalChar "%targetDir%" "%newDirectory%"
set equalCharTotal=!errorlevel!
call :readFileList "%souceFile%"
call :getTargetinfo "%targetDir%"
call :matchTarget
call :deleteSourceFile

pause & exit

REM 计算顶部路径相同部分
:equalTotalChar
    set sourcePath=%~1
    set newPath=%~2
    for /l %%i in (0,1,255) do (
        if /i "!sourcePath:~%%i,1!" neq "!newPath:~%%i,1!" (
            if /i "!sourcePath:~%%i,1!" equ "\" (exit /b %%i) else (
                for /l %%b in (%%i,-1,0) do (
                    if "!sourcePath:~%%b,1!" equ "\" (exit /b %%b)
                )
            )
        )
    )
    exit /b 0

REM 读取文件列表
:readFileList
    set fileName=%1
    set /a sourceFileLines = 0
    for /f "tokens=*" %%L in ('type %fileName%') do (set /a sourceFileLines+=1 & set "source_!sourceFileLines!=%%L")
    exit /b

REM 获取目标目录信息
:getTargetinfo
    set targetDirectory=%1
    set /a targetNumber=0
    for /f "tokens=*" %%u in ('dir /b /s %targetDirectory%') do (set /a targetNumber+=1 & set "target_!targetNumber!=%%u")
    exit /b
    
REM 匹配目标
:matchTarget
    echo 数据源数量为:%sourceFileLines%
    set /a deleteNumber=0
    echo %date% %time% >> %notFoundFileName%
    for /l %%s in (1,1,%sourceFileLines%) do (
        echo 正在处理第 %%s 个,!source_%%s!
        set found=false
        for /l %%t in (1,1,%targetNumber%) do (
            call :getFileOrDirectoryName "!source_%%s!" "!target_%%t!" & set matchResult=!errorlevel!
            if !matchResult! equ 1 (
                set found=true
                set "tempNewDirOrFile=%newDirectory%!target_%%t:~%equalCharTotal%!"
                pushd "!target_%%t!" && popd & (
                    if not exist "!tempNewDirOrFile!" (
                        md "!tempNewDirOrFile!" && xcopy /e /y "!target_%%t!" "!tempNewDirOrFile!"
                    )
                ) || (
                    if exist "!tempNewDirOrFile!" (
                        echo f | xcopy /y "!target_%%t!" "!tempNewDirOrFile!"
                    ) else (
                        echo f | xcopy "!target_%%t!" "!tempNewDirOrFile!"
                    )
                )
                set /a deleteNumber+=1 & set "deleteSourceFileOrDirectory_!deleteNumber!=!target_%%t!"
            ) 1>nul 2>nul
        ) 
        if "!found!" equ "false" (
            echo !source_%%s! >> %notFoundFileName%
        )
    )
    exit /b

REM 匹配 目标判断
:getFileOrDirectoryName
    set "souce=%1"
    set "target=%~nx2"
    if %souce% == "%target%" (exit /b 1)
    exit /b 0

REM 删除源文件
:deleteSourceFile
    echo 是否删除所有原路径下已经被复制的文件和文件夹?
    echo 输入 Y 是,N 否:
    choice
    set input=%errorlevel%
    if %input% neq 1 (exit /b) 
    for /l %%n in (1,1,!deleteNumber!) do (del /p /s !deleteSourceFileOrDirectory_%%n!)
    exit /b

C# 源代码
[C#] 纯文本查看 复制代码
using System;
using System.IO;
using System.Collections.Generic;
using System.Threading.Tasks;

class Program
{
    static void Main()
    {
        string sourceFile = "files.txt";
        string targetPath = @"d:\gin\c#";
        string newDirectory = @"d:\gin\NewDirectory";
        string[] SourceFileContent = File.ReadAllLines(sourceFile, System.Text.Encoding.Default);
        
        List<string> TargetAllDir;
        List<string> TargetAllDirName = GetFileName(Directory.EnumerateDirectories(targetPath, "*", SearchOption.AllDirectories), out TargetAllDir);
        
        List<string> TargetAllFile;
        List<string> TargetAllFileName = GetFileName(Directory.EnumerateFiles(targetPath, "*", SearchOption.AllDirectories), out TargetAllFile);
        
        List<int> res;
        bool found = false;
        foreach (string source in SourceFileContent)
        {
            found = false;
            // 复制目录(树)
            res = FindDirAndFileName(source, TargetAllDirName);
            if (res.Count > 0)
            {
                found = true;
                foreach (int index in res)
                {
                    
                    // 复制目录结构
                    string newTargetDir = PathReplace(TargetAllDir[index], newDirectory);
                    if (!Directory.Exists(newTargetDir))
                    {
                        Directory.CreateDirectory(newTargetDir);
                    }
                    
                    foreach (string subDir in Directory.EnumerateDirectories(TargetAllDir[index], "*", SearchOption.AllDirectories))
                    {
                        string newSubDir = PathReplace(subDir, newDirectory);
                        if (!Directory.Exists(newSubDir))
                        {
                            Directory.CreateDirectory(newSubDir);
                        }
                    }
                    
                    // 复制文件
                    foreach (string subFile in Directory.EnumerateFiles(TargetAllDir[index], "*", SearchOption.AllDirectories))
                    {
                        File.Copy(subFile, PathReplace(subFile, newDirectory), true);
                    }
                }
            }
            
            // Console.WriteLine(1);
            // 复制文件
            res = FindDirAndFileName(source, TargetAllFileName);
            if (res.Count > 0)
            {
                found = true;
                foreach (int index in res)
                {
                    string newFileFullName = PathReplace(TargetAllFile[index], newDirectory);
                    string newFileFullDir = Path.GetDirectoryName(newFileFullName);
                    if (!Directory.Exists(newFileFullDir))
                    {
                        Directory.CreateDirectory(newFileFullDir);
                    }
                    File.Copy(TargetAllFile[index], newFileFullName, true);
                }
            }
            
            if (!found)
            {
                Console.WriteLine("{0} 未找到!", source);
            }
        }
        
    }
    
    // 扫描目标目录文件目录结构
    static List<string> GetFileName(IEnumerable<string> Data, out List<string> ToTList)
    {
        List<string> FileName = new List<string>();
        ToTList = new List<string>();
        foreach (var dir in Data)
        {
            FileName.Add(Path.GetFileName(dir));
            ToTList.Add(dir);
        }
        return FileName;
    }
    
    // 查找文件或者目录
    static List<int> FindDirAndFileName(string source, List<string> Target)
    {
        List<int> result = new List<int>();
        int index = Target.IndexOf(source);
        if (index == -1) return result;
        result.Add(index);
        while (true)
        {
           index = Target.IndexOf(source, index + 1);
           if (index != -1)
           {
               result.Add(index);
           }
           else
           {
               break;
           }
        }
        return result;
    }
    
    // 路径替换
    static string PathReplace(string source, string newDirectory)
    {
        string newPath ;
        // 判断是否在一个盘符下面
        if (Path.GetPathRoot(source).ToUpper() == Path.GetPathRoot(newDirectory).ToUpper())
        {
            int index = 0;
            while (index < newDirectory.Length)
            {
                if (char.ToUpper(source[index]) == char.ToUpper(newDirectory[index]))
                {
                    index++;
                }
                else
                {
                    break;
                }
            }
            while (true)
            {
                if (source[--index] == '\\')
                {
                    newPath = Path.Combine(newDirectory, source.Substring(index + 1));
                    break;
                }
            }
        }
        else
        {
            newPath = Path.Combine(newDirectory, source.Substring(3));
        }
        return newPath;
    }
}

免费评分

参与人数 2吾爱币 +2 热心值 +2 收起 理由
泡泡汽水 + 1 + 1 用心讨论,共获提升!
newease + 1 + 1 热心回复!

查看全部评分

发帖前要善用论坛搜索功能,那里可能会有你要找的答案或者已经有人发布过相同内容了,请勿重复发帖。

 楼主| Cool_Breeze 发表于 2021-5-28 16:30
QQending 发表于 2021-5-28 14:30
对的,打包exe,主要是包太大了

不过说实话,本人,一方面批处理写的少,不光对语法,对换行也不熟练 ...

https://docs.microsoft.com/zh-cn ... ndows-commands/echo
本路人 发表于 2021-5-28 14:15
Cool_Breeze 发表于 2021-5-28 13:57
python处理起来更方便!

python自用自然好,但如果给别人尤其是电脑小白使用还要打包exe啊,不然别人没有python环境的用不了
本路人 发表于 2021-5-28 13:37
不错,谢谢分享。虽然我自己是用py脚本去做的,没有批处理可以直接发给别人就能使用了这样方便
as614001 发表于 2021-5-28 13:38
记得缺点好像是 不能中文路径
sutramusic 发表于 2021-5-28 13:39
多谢楼主分享!
newease 发表于 2021-5-28 13:46
感谢楼主分享,有空试试,加分致谢
泡泡汽水 发表于 2021-5-28 13:51
真不错 解决了大量文件复制粘贴的事情了
 楼主| Cool_Breeze 发表于 2021-5-28 13:55
as614001 发表于 2021-5-28 13:38
记得缺点好像是 不能中文路径

合法的路径应该是可以的。但是没有测试过。
 楼主| Cool_Breeze 发表于 2021-5-28 13:57
本路人 发表于 2021-5-28 13:37
不错,谢谢分享。虽然我自己是用py脚本去做的,没有批处理可以直接发给别人就能使用了这样方便

python处理起来更方便!
a945882813 发表于 2021-5-28 14:02
学习了!
您需要登录后才可以回帖 登录 | 注册[Register]

本版积分规则 警告:本版块禁止灌水或回复与主题无关内容,违者重罚!

快速回复 收藏帖子 返回列表 搜索

RSS订阅|小黑屋|处罚记录|联系我们|吾爱破解 - LCG - LSG ( 京ICP备16042023号 | 京公网安备 11010502030087号 )

GMT+8, 2024-4-26 06:55

Powered by Discuz!

Copyright © 2001-2020, Tencent Cloud.

快速回复 返回顶部 返回列表