使用 PowerShell 批量复制和重命名文件 [英] Batch copy and rename files with PowerShell

查看:340
本文介绍了使用 PowerShell 批量复制和重命名文件的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在尝试使用 PowerShell 批量复制和重命名文件.

I'm trying to use PowerShell to batch copy and rename files.

原始文件命名为AAA001A.jpg、AAB002A.jpg、AAB003A.jpg等

The original files are named AAA001A.jpg, AAB002A.jpg, AAB003A.jpg, etc.

我想复制具有新名称的文件,方法是去掉文件名的前四个字符和句点前的字符,使复制的文件命名为 01.jpg、02.jpg、03.jpg等

I'd like to copy the files with new names, by stripping the first four characters from the filenames, and the character before the period, so that the copied files are named 01.jpg, 02.jpg, 03.jpg, etc.

我有在 Linux 上使用 Bash 脚本的经验,但我对如何使用 PowerShell 执行此操作感到困惑.经过几个小时的反复试验,这与我得到的结果非常接近:

I have experience with Bash scripts on Linux, but I'm stumped on how to do this with PowerShell. After a couple of hours of trial-and-error, this is as close as I've gotten:

Get-ChildItem AAB002A.jpg | foreach { copy-item $_ "$_.name.replace ("AAB","")" }

(它不起作用)

推荐答案

注意:
* 虽然可能比 abelenky 的答案 稍微复杂一些,但它 (a) 更强大,因为它确保只有 *.jpg 符合所需模式的文件被处理,(b) 展示了一些高级正则表达式技术,(c) 提供背景信息并解释 OP 方法的问题.
* 此答案使用 PSv3+ 语法.

Note:
* While perhaps slightly more complex than abelenky's answer, it (a) is more robust in that it ensures that only *.jpg files that fit the desired pattern are processed, (b) shows some advanced regex techniques, (c) provides background information and explains the problem with the OP's approach.
* This answer uses PSv3+ syntax.

Get-ChildItem *.jpg |
  Where-Object Name -match '^.{4}(.+).\.(.+)$' | 
    Copy-Item -Destination { $Matches.1 + '.' + $Matches.2 } -WhatIf

为了保持命令简短,目标目录没有明确控制,所以副本将放置在当前目录中.确保放置在同一目录中.作为输入文件,使用
Join-Path $_.PSParentPath ($Matches.1 + '.' + $Matches.2) { ... }.

-WhatIf 预览 将复制到哪些文件;删除它以执行实际复制.

-WhatIf previews what files would be copied to; remove it to perform actual copying.

  • Get-ChildItem *.jpg 输出所有 *.jpg 文件 - 无论它们是否符合要重命名的文件模式.

  • Get-ChildItem *.jpg outputs all *.jpg files - whether or not they fit the pattern of files to be renamed.

Where-Object Name -match '^.{4}(.*).\.(.+)$' 然后将匹配范围缩小到符合模式的那些,使用 regex(正则表达式):

Where-Object Name -match '^.{4}(.*).\.(.+)$' then narrows the matches down to those that fit the pattern, using a regex (regular expression):

  • ^...$ 锚定正则表达式以确保它匹配 整个 输入(^ 匹配输入的开头,和 $ 结束).
  • .{4} 匹配前 4 个字符 (.),无论它们是什么.
  • (.+) 匹配任何非空字符序列,并且由于包含在 (...) 中,因此在 捕获组中捕获该序列,反映在自动 $Matches 变量中,可作为 $Matches.1 访问(因为是第一个捕获组).
  • . 匹配文件扩展名之前的字符.
  • \. 匹配 literal .,因为被 \ 转义 - 即扩展名.
  • (.+) 是捕获文件扩展名的第二个捕获组(没有前面的 . 文字),可作为 $Matches.2.
  • ^...$ anchors the regular expression to ensure that it matches the whole input (^ matches the start of the input, and $ its end).
  • .{4} matches the first 4 characters (.), whatever they may be.
  • (.+) matches any nonempty sequence of characters and, due to being enclosed in (...), captures that sequence in a capture group, which is reflected in the automatic $Matches variable, accessible as $Matches.1 (due to being the first capture group).
  • . matches the character just before the filename extension.
  • \. matches a literal ., due to being escaped with \ - i.e., the start of the extension.
  • (.+) is the 2nd capture group that captures the filename extension (without the preceding . literal), accessible as $Matches.2.

Copy-Item -Destination { $Matches.1 + '.'+ $Matches.2 } 然后根据从输入文件名中提取的捕获组值重命名每个输入文件.

Copy-Item -Destination { $Matches.1 + '.' + $Matches.2 } then renames each input file based on the capture-group values extracted from the input filenames.

  • 通常,如果可行,直接管道到 cmdlet 总是优于管道到 Foreach-Object cmdlet(其内置别名是 foreach),出于性能原因.在上面的 Copy-Item 命令中,目标路径是通过 script-block 参数 指定的,该参数通过 $_ 绑定到手头的输入文件.

  • Generally, directly piping to a cmdlet, if feasible, is always preferable to piping to the Foreach-Object cmdlet (whose built-in alias is foreach), for performance reasons.
    In the Copy-Item command above, the target path is specified via a script-block argument, which is evaluated for each input path with $_ bound to the input file at hand.

注意:上面假设副本应该放在当前目录中,因为脚本块输出的只是一个文件名,而不是一个路径.

Note: The above assumes that the copies should be placed in the current directory, because the script block outputs a mere filename, not a path.

  • 要明确控制目标路径,请在 -Destination 脚本块内使用 Join-Path.
    例如,确保副本始终与输入文件放在同一文件夹中 - 无论当前目录是什么.是 - 使用:
    Join-Path $_.PSParentPath ($Matches.1 + '.' + $Matches.2)
  • To control the target path explicitly, use Join-Path inside the -Destination script block.
    For instance, to ensure that the copies are always placed in the same folder as the input files - irrespective of what the current dir. is - use:
    Join-Path $_.PSParentPath ($Matches.1 + '.' + $Matches.2)

至于你尝试过的:

  • "..."(双引号字符串)中,必须使用$(...)子表达式运算符,以便嵌入应该用其值替换的表达式.

  • Inside "..." (double-quoted strings), you must use $(...), the subexpression operator, in order to embed expressions that should be replaced with their value.

无论如何,.replace ("AAB", "") (a) 由于空格字符而在语法上中断.( 之前(您是否混淆了 [string] 类型的 .Replace() method 与 PowerShell 的 -replace operator?),(b) 硬编码要删除的前缀,(c) 限制为 3 个字符,(d) 不删除句点前的字符.

Irrespective of that, .replace ("AAB", "") (a) breaks syntactically due to the space char. before ( (did you confuse the [string] type's .Replace() method with PowerShell's -replace operator?), (b) hard-codes the prefix to remove, (c) is limited to 3 characters, and (d) doesn't remove the character before the period.

目的地位置警告也适用:如果您的表达式有效,它只会计算一个文件名,这会将结果文件放在当前 目录而不是与输入文件相同的目录(尽管这不会有问题,如果您从当前目录运行命令.或者如果这是您的实际意图).

The destination-location caveat applies as well: If your expression worked, it would only evaluate to a filename, which would place the resulting file in the current directory rather than the same directory as the input file (though that wouldn't be a problem, if you ran the command from the current dir. or if that is your actual intent).

这篇关于使用 PowerShell 批量复制和重命名文件的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆