当前位置: 首页 > 知识库问答 >
问题:

通过跳过哈希(#)将. png文件名的重复名称列出为文本文件

奚和光
2023-03-14

我正在尝试检查如何检查所有具有相同名称的文件名,并希望将这些相似的文件名与文件夹路径分组,然后将它们导出到文本文件。

到目前为止,我已经编写了以下代码,可以在每个。png文件名,并在#之后成功添加数字。但我无法通过跳过#和之后的数字来检查重复的名字。

我所有的文件名都是. png格式。

我有超过100个子文件夹,每个文件夹都有超过2个文件,最多25个. png文件。

文件命名样式:

非常感谢您的建议!

 private void button1_Click(object sender, EventArgs e)
        {
            FolderBrowserDialog folderDlg = new FolderBrowserDialog();
            folderDlg.SelectedPath = "C:\\Users\\demo\\Documents\\process\\";
            if (folderDlg.ShowDialog() != DialogResult.OK)
            {
                return;
            }

            // Has different framework dependend implementations 
            // in order to handle unauthorized access to subfolders
            RenameAllPngFiles(folderDlg.SelectedPath);
        }
        private void RenameAllPngFiles(string directoryPath)
        {
            RenameCurrentPng(directoryPath);
            foreach (var item in GetDirectoryInfos(directoryPath))
            {
                RenameCurrentPng(item.FullName);
            }
        }

        private void RenameCurrentPng(string directoryPath)
        {
            int fileNameSuffixCounter = 1;
            foreach (string originalFullFileName in Directory.EnumerateFiles(directoryPath, "*.png"))
            {
                string ShortFileName = System.IO.Path.GetFileNameWithoutExtension(originalFullFileName);
                if (!ShortFileName.Contains("#"))
                {
                    // The new file name without path
                    var newFileName = $"{ShortFileName}#{fileNameSuffixCounter++}{System.IO.Path.GetExtension(originalFullFileName)}";
                    FileSystem.RenameFile(originalFullFileName, newFileName);
                }
            }
        }

        private DirectoryInfo[] GetDirectoryInfos(string directoryPath)
        {
            DirectoryInfo di = new DirectoryInfo(directoryPath);
            DirectoryInfo[] directories = di.GetDirectories("*", System.IO.SearchOption.AllDirectories);
            return directories;
    }

共有1个答案

夏高朗
2023-03-14

这将根据#之前的名称片段对文件进行分组,并通过在所有子文件夹中添加唯一的编号来建议新名称

    var fs = Directory.GetFiles("c:\\temp\\a", "*.*", SearchOption.AllDirectories);

    var changes = fs
        .GroupBy(f => Path.GetFileName(f).Split('#', 2)[0],
          (k, g) => g.Select((f, i) => new
          {
              OldPath = f,
              NewPath = Path.Combine(Path.GetDirectoryName(f), $"{k}#{i}{Path.GetExtension(f)}")
          })
        );

那么它是做什么的呢?

  • 将所有目录中的所有文件枚举到fs
  • 文件名分组fs。拆分('#',2)[0]这意味着“在#上拆分,最多返回2个子字符串,因为我们只需要第一个,以第一个作为要分组的东西”
  • 这会导致将所有不同的a#xx.txt分组到一个列表中。GroupBy的第二个参数就像在分组的结果上运行一个选择(所有文件路径的“数组”,名称以a开头)
    • k是键,即a#1.txt中的a'b#1.txt中的b
    • g是完整文件路径的组(数组)
    • f是项,即完整路径,
    • i是“数组”中的索引,即该文件名的唯一编号。
    • 原始完整路径f的OldPath,和
    • NewPathf的目录,加上第一个#之前的所有内容的组的键,加上一个#,加上唯一的数字i,加上f
    • 的扩展名

    我想,如果您想运行一些重命名,将它们作为旧/新名称对的列表会很方便。还有其他一些事情可能是明智的;有一个临时的、保证唯一的文件名,我们首先将其移动到:

    var flatListWithTempName = changes.SelectMany(x => x, x =>
      new { 
        x.OldPath,
        x.NewPath, 
        TempPath = x.OldPath + Guid.NewGuid()
      }
    ).ToArray();
    
    foreach(var change in flatListWithTempName){
      File.Move(change.OldPath, change.TempPath);
    }
    
    foreach(var change in flatListWithTempName){
      File.Move(change.TempPath, change.NewPath);
    }
    

    SelectMany将打开一层巢穴。第二个参数将旧/新路径重塑为也具有新guid的临时路径。为什么要这样做?

    好吧,假设出于某种原因,您的一个重命名是a#1。txt-

    如果有帮助,请使用稍长的变量名:

    var fullPathsOfAllFiles = Directory.GetFiles("c:\\temp\\a", "*.*", SearchOption.AllDirectories);
    
    var changes = fullPathsOfAllFiles 
            .GroupBy(fullPathOfOneFile => Path.GetFileName(fullPathOfOneFile).Split('#', 2)[0],
              (partialNameBeforeHash, fullPathsWithThatPartial) => arrayOfFullPathsWithThatPartial.Select((fullPath, arrayIndex) => new
              {
                  OldPath = fullPath,
                  NewPath = Path.Combine(Path.GetDirectoryName(fullPath), $"{partialNameBeforeHash}#{arrayIndex}{Path.GetExtension(fullPath)}")
              })
            );
    

    我说“数组”,因为它在这些目的上就像一个数组,但它实际上是一个可枚举的

    这是一个具有重复名称的文件结构:

    这是组结果的内容。您可以看到NewPath中所有重新编号的文件,从0开始,所有文件名都是唯一的:

    https://imgs.xnip.cn/cj/n/21/bb646420-535c-43ad-9995-ddb548e49af5.png" width="100%" height="100%" />

 类似资料:
  • 问题 你需要写一个涉及到文件查找操作的脚本,比如对日志归档文件的重命名工具, 你不想在Python脚本中调用shell,或者你要实现一些shell不能做的功能。 解决方案 查找文件,可使用 os.walk() 函数,传一个顶级目录名给它。 下面是一个例子,查找特定的文件名并答应所有符合条件的文件全路径: #!/usr/bin/env python3.3 import os def findfil

  • 我正在使用Spring集成RemoteFileTemplate通过Sftp下载文件。如何对正在下载的每个文件名执行一些处理?我看到那条线 .log(logginghandler.level.info,“sftp.inbound”,message::getheaders) 记录文件名,但我需要直接可用的文件名。 我需要做的只是将下载的文件名作为列表写入POJO中,以便作为响应传递给稍后的进程。我的代

  • 我尝试使用jarsigner通过以下命令对。apk文件进行签名:- C:\program files\java\jdk1.7.0_25\bin>jarsigner-keystore“C:\program files.android\debug.keystore”-storePass android-keypass android“C:\program files.android\androidca

  • 我在不同的文件夹中动态创建文件,像这样: 这给了我: 但由于我正在许多文件夹中创建同名文件,因此我希望通过添加文件夹名称作为前缀来区分它们,以获得: 我怎么能得到这个?

  • 问题内容: 我知道以前已经问过这个问题,并且已经看到了一些答案,但是这个问题更多地是关于我的代码和完成此任务的最佳方法。 我想扫描一个目录,并查看该目录中是否存在任何重复项(通过检查MD5哈希值)。以下是我的代码: 这给了我以下输出: 我的想法是: 1)扫描目录2)将MD5哈希+文件名写入文本文件3)以只读方式打开文本文件4)再次扫描目录并检查文本文件… 我看到这不是一个好方法,而且行不通。“匹配