【问题标题】:Batch or Bash to remove a timestamp in thousands of files [closed]批处理或 Bash 删除数千个文件中的时间戳 [关闭]
【发布时间】:2017-02-19 04:24:18
【问题描述】:

我今天在处理自托管备份系统时犯了一个重大错误,最终删除了大约一半的用户文件夹。幸运的是,备份存在并且能够复制我的所有数据。不好的部分是每个恢复的文件在文件名中都有一个时间戳。

所以原来是 filename.file 的文件现在是 filename~20170401-1999.file

对于批处理文件或其他什么,我不太聪明,但是有什么办法可以对 BAT 进行编程以遍历每个文件名并取出时间戳?每个时间戳都以 ~ 开头,以文件类型的句点结尾。因此,删除包括代字号和代字号之后的所有内容并在句号之前停在字符处将解决问题。

有大约 4600 个文件需要使用各种文件类型扩展名进行修复。我在 Windows 10 Pro 上并且能够使用 powershell 或 bash 来修复错误。我已经安装了 Windows Linux 子系统,所以也可以使用 bash 脚本。

【问题讨论】:

  • 每个文件名中是否总是恰好出现一个~
  • 已经有了答案,但是是的,它在从备份恢复的每个文件中只出现一次。未恢复的文件只是 filename.type 而恢复的文件是 filename~dategroup-timegroup.type (I.E. resume~20170409-173314.pdf
  • 可以使用 Internet 上任何免费提供的文件重命名实用程序轻松完成此操作。

标签: windows bash powershell batch-file filenames


【解决方案1】:

PowerShell 提供了一个简单的解决方案:

Get-ChildItem -Recurse -File -Filter *~* | 
  Rename-Item -NewName { $_.Name -replace '~[^.]+' } -WhatIf
  • -WhatIf预览重命名操作;一旦您确认该命令将按预期工作,请将其删除。

  • 为简单起见,我假设任何包含~ 的文件名都必须重命名;如果必须消除误报,则可以改进匹配:
    Get-ChildItem -Recurse -File *~[0-9][0-9][0-9][0-9][0-9][0-9][0-9][0-9]-[0-9][0-9][0-9][0-9].*

  • 匹配仅限于位于当前目录子树 (-Recurse) 中任意位置的文件 (-File)。
    要仅匹配当前目录中直接的文件,请删除-Recurse

  • 传递给Rename-Item cmdlet 的-NewName 参数的脚本块({ ... }) 计算新文件名:

    • $_.Name 返回输入文件的名称($_ 是 PowerShell 的自动变量,用于表示手头的输入对象)。
    • -replace '~[^.]+' 执行基于正则表达式的字符串替换:'~[^.]+' 匹配 ~ 后跟任何非空字符序列 (+),而不是 . ([^.])。不指定替换字符串会隐式使用空字符串,以便有效地从名称中删除匹配部分。

【讨论】:

    【解决方案2】:

    只是我脑海中的一些想法。

    您可以遍历文件,对于每个文件名,您可以将匹配正则表达式/~\d+-\d+/ 的子字符串替换为""(即空字符串),并将修改后的字符串用作文件的新名称。

    【讨论】:

      【解决方案3】:
      @ECHO OFF
      SETLOCAL
      
      SET "sourcedir=U:\sourcedir"
      FOR /f "delims=" %%a IN (
       'dir /b /s /a-d "%sourcedir%\*" '
       ) DO (
       FOR /f "tokens=1,2delims=~" %%p IN ("%%~na") DO (
        IF "%%q" neq "" ECHO(REN "%%a" "%%~p%%~xa"
       )
      )
      
      GOTO :EOF
      

      您需要更改sourcedir 的设置以适应您的情况。

      所需的 REN 命令仅用于测试目的ECHOed。 验证命令正确后,将ECHO(REN 更改为REN 以实际重命名文件。

      对基本形式的子目录执行目录扫描,没有目录名并分配给%%a。然后使用~ 作为分隔符将找到的全名的名称部分标记为%%p%%q。如果第二个令牌不为空,那么我们在%%q 中有一个时间戳,因此从%%p 的部分和%%a 的扩展名形成新文件名

      【讨论】:

        【解决方案4】:

        没有正则表达式的 mklement0 的变体

         Get-ChildItem -Recurse -File -Filter *~*.file | 
             rename-item -NewName {"{0}{1}" -f ($_.BaseName -split "~")[0], $_.Extension  } -WhatIf
        

        一个简短的版本:

         gci -Rec -File -Filter *~*.file | ren -n {"{0}{1}" -f ($_.Base -split "~")[0], $_.Extension  } -WhatIf
        

        【讨论】:

          猜你喜欢
          • 2014-12-17
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2018-12-28
          • 1970-01-01
          相关资源
          最近更新 更多