【问题标题】:Rename multiple files in one directory重命名一个目录中的多个文件
【发布时间】:2019-06-08 04:17:31
【问题描述】:

是否可以使用 vb.NET 用一个简单的程序重命名文件夹中的所有文件

假设有一个包含文件的文件夹,每次加载文件都会有所不同:

A123.txt B456.txt C567.txt

是否可以在一次操作中重命名这些文件,如下所示:

A_1.txt B_2.txt B_3.txt

【问题讨论】:

  • 有可能。你只需要找到一个明确的规则,新名称是如何根据原名称生成的。
  • 不能...好像C567.txt应该重命名为B_3.txt,不知道为什么会这样。
  • 我认为 the_lotus 试图说我们不知道您的编号规则。只有您可以知道,然后您需要对其进行编码。我唯一要添加的建议是,一旦您知道您的规则,您就可以在运行重命名之前检查是否有任何文件不遵循该规则。然后,当您运行规则时,请确保您没有重复使用您之前在该文件夹中处理过的名称。
  • in one operation 不,System.IO 是您用于文件操作的命名空间,我所知道的其中没有任何内容可以在单个操作中执行此操作。但是您可以按照您的建议编写循环或使用“多线程”。
  • System.IO 的 DirectoryInfo 类将使用 GetFiles() 方法返回该目录的文件。由此,您可以遍历文件并使用 File 类 / Move() 方法重命名文件。但是在重命名过程中(在这样做之前),请检查您是否已经将另一个文件重命名为您将要使用的名称。 File.Exists 方法将确保您的安全。

标签: asp.net vb.net


【解决方案1】:

这可以简化,但这里是每一步都有 cmets 的长版本

Imports System.IO


' get your filenames to be renamed
Dim filenames = Directory.GetFiles("c:\path\with\files")
' order them by whatever rule you choose (here it is by modification date)
Dim orderedFilenames = filenames.OrderBy(Function(s) File.GetLastWriteTime(s))
' rename the files into a dictionary<oldname, newname>
' will result in filename X_Y.Z where X is first letter, Y is order index, Z is extension
Dim newNameSelector =
    Function(s As String, i As Integer)
        Return New KeyValuePair(Of String, String)(s,
            Path.Combine(Path.GetDirectoryName(s), $"{Path.GetFileName(s)(0)}_{i}{Path.GetExtension(s)}"))
    End Function
' get new names using the newNameSelector function
Dim newNames = orderedFilenames.Select(newNameSelector)
' define the operation to rename the file using a keyvaluepair<oldname, newname>
Dim renameMethod = Sub(kvp As KeyValuePair(Of String, String)) File.Move(kvp.Key, kvp.Value)
' either sequential rename ...
For Each newName In newNames
    renameMethod(newName)
Next
' ... or it could be multi threaded
Parallel.ForEach(newNames, renameOperation)

注意事项:

  • 根据使用文件索引的重命名规则,不需要进行 File.Exists 检查。如果您更改规则,则可能有必要。您的问题正文中的规则不明确。这假设它只运行一次。
  • 字典键将是唯一的,因为 Windows 不会有重复的文件名

要回答您的问题,Will it be possible to rename these files in one operation[?],不,但我们可以在一个“行”中完成,甚至可以使用多个线程。只需修改路径字符串“c:\path\with\files”并运行此代码

Parallel.ForEach(Directory.GetFiles("c:\path\with\files").OrderBy(Function(s) File.GetLastWriteTime(s)).Select(Function(s, i) New KeyValuePair(Of String, String)(s, Path.Combine(Path.GetDirectoryName(s), $"{Path.GetFileName(s)(0)}_{i}{Path.GetExtension(s)}"))), Sub(kvp) File.Move(kvp.Key, kvp.Value))

我认为您可能需要制定重命名逻辑。这就是我在长代码示例中将其分开的原因。只需处理 newNameSelector 内部的逻辑即可。

如果您想按名称订购,只需

Dim orderedFilenames = filenames.OrderBy(Function(s) s)

这将从您的文件名中删除“_20190607”

Dim newNameSelector =
    Function(s As String)
        Return New KeyValuePair(Of String, String)(s,
            Path.Combine(Path.GetDirectoryName(s), String.Format("{0}{1}", Path.GetFileName(s).Split("_"c)(0), Path.GetExtension(s))))
    End Function

我知道这个答案越来越难以理解,但 OP 不断提供新信息,这意味着问题正在发生变化,因此答案也是如此。根据他最近的评论,应该只重命名每个前缀中最早的一个。

' group the filenames into groups using key: "prefix_"
Dim groupedFilenames = Directory.GetFiles("c:\path\with\files").GroupBy(Function(s) Path.GetFileName(s).Split("_"c)(0))
Dim filenames As New List(Of String)()
' add the min from each group, using the name as the comparer
For Each g In groupedFilenames
    filenames.Add(g.Min(Function(s) s))
Next
' rename the files into a dictionary<oldname, newname>
' will result in filename X_Y.Z where X is first letter, Y is order index, Z is extension
Dim newNameSelector =
    Function(s As String)
        Return New KeyValuePair(Of String, String)(s,
            Path.Combine(Path.GetDirectoryName(s), String.Format("{0}{1}", Path.GetFileName(s).Split("_"c)(0), Path.GetExtension(s))))
    End Function
' get new names using the newNameSelector function
Dim newNames = filenames.Select(newNameSelector)
' define the operation to rename the file using a keyvaluepair<oldname, newname>
Dim renameOperation = Sub(kvp As KeyValuePair(Of String, String)) File.Move(kvp.Key, kvp.Value)
' ... or it could be multi threaded
Parallel.ForEach(newNames, renameOperation)

【讨论】:

  • 感谢您的回复 我没有得到您的代码 我想要简单的代码来处理我的案例 我是 ASP.NET VB 的初学者,请解释更多细节,以便我确保代码正常工作跨度>
  • @Mahmoud 确保您阅读了我的回答。几乎每一行都有 cmets 的详细信息。
  • 谢谢,我会这样做,但在您的代码中,$ 符号是不可能的字符,还有没有办法按名称对文件进行排序?
  • @Mahmoud 您可能使用的是旧版本的 Visual Studio 和 .NET 框架。您可以将$"{Path.GetFileName(s)(0)}_{i}{Path.GetExtension(s)}" 更改为String.Format("{0}_{1}{2}", Path.GetFileName(s)(0), i, Path.GetExtension(s))
  • 它的工作很棒,但如果我想按名称订购文件,你没有回答我的第二个问题,这可能吗?
猜你喜欢
  • 2018-11-01
  • 2018-01-19
  • 1970-01-01
  • 2012-12-27
  • 2018-08-29
  • 1970-01-01
  • 2019-11-13
  • 2015-04-23
  • 2021-05-10
相关资源
最近更新 更多