[英]How to recursively append to file name in powershell?
I have multiple .txt files in folders/their sub-folders.我在文件夹/它们的子文件夹中有多个 .txt 文件。
I want to append _old to their file names.我想将 _old 附加到他们的文件名。
I tried:我试过:
Get-ChildItem -Recurse | Rename-Item -NewName {$_.name -replace '.txt','_old.txt' }
This results in:这导致:
.._old_old.txt
.._old_old.txt
Rename-Item : Source and destination path must be different.
Rename-Item : Source and destination path must be different.
To prevent already renamed files from accidentally reentering the file enumeration and therefore getting renamed multiple times, enclose your Get-ChildItem
call in ()
, the grouping operator , which ensures that all output is collected first [1] , before sending the results through the pipeline:为了防止已重命名的文件意外地重新进入该文件列举,因此越来越改名多次,附上您
Get-ChildItem
呼叫()
在分组操作,以保证所有输出首先收集[1],通过发送结果之前管道:
(Get-ChildItem -Recurse) |
Rename-Item -NewName { $_.name -replace '\.txt$', '_old.txt' }
Note that I've used \\.txt$
as the regex [2] , so as to ensure that only a literal .
请注意,我使用
\\.txt$
作为正则表达式[2] ,以确保只有文字.
( \\.
) followed by string txt
at the end ( $
) of the file name is matched, so as to prevent false positives (eg, a file named Atxt.csv
or even a directory named AtxtB
would accidentally match your original regex). (
\\.
) 后跟字符串txt
在文件名的末尾( $
) 匹配,以防止误报(例如,名为Atxt.csv
的文件甚至名为AtxtB
的目录会意外匹配您的原始正则表达式)。
Note: The need to collect all Get-ChildItem
output first arises from how the PowerShell pipeline fundamentally works: objects are (by default) sent to the pipeline one by one , and processed by a receiving command as they're being received .注意:收集所有
Get-ChildItem
输出的需要首先源于 PowerShell 管道的基本工作方式:对象(默认情况下)一个接一个地发送到管道,并在接收到它们时由接收命令处理。 This means that, without (...)
around Get-ChildItem
, Rename-Item
starts renaming files before Get-ChildItem
has finished enumerating files, which causes problems.这意味着,在
Get-ChildItem
周围没有(...)
, Rename-Item
在Get-ChildItem
完成枚举文件之前开始重命名文件,这会导致问题。 See this answer for more information about how the PowerShell pipeline works.有关 PowerShell 管道如何工作的更多信息,请参阅此答案。
Tip of the hat to Matthew for suggesting inclusion of this information.向Matthew 表示感谢,他建议包含此信息。
However, I suggest optimizing your command as follows:但是,我建议按如下方式优化您的命令:
(Get-ChildItem -Recurse -File -Filter *.txt) |
Rename-Item -NewName { $_.BaseName + '_old' + $_.Extension }
-File
limits the the output to files (doesn't also return directories ). -File
将输出限制为文件(也不返回目录)。
-Filter
is the fastest way to limit results to a given wildcard pattern. -Filter
是将结果限制为给定通配符模式的最快方法。
$_.BaseName + '_old' + $_.Extension
uses simple string concatenation via the sub-components of a file name. $_.BaseName + '_old' + $_.Extension
通过文件名的子组件使用简单的字符串连接。
-replace
:-replace
:$_.Name -replace '\\.[^.]+$', '_old$&'
Note that if you wanted to run this repeatedly and needed to exclude files renamed in a previous run, add -Exclude *_old.txt
to the Get-ChildItem
call.请注意,如果您想重复运行此操作并需要排除在前一次运行中重命名的文件,请将
-Exclude *_old.txt
添加到Get-ChildItem
调用中。
[1] Due to a change in how Get-ChildItem
is implemented in PowerShell [Core] 6+ (it now internally sorts the results, which invariably requires collecting them all first), the (...)
enclosure is no longer strictly necessary , but this could be considered an implementation detail, so for conceptual clarity it's better to continue to use (...)
. [1] 由于在PowerShell [Core] 6+ 中实现
Get-ChildItem
的方式发生了变化(它现在在内部对结果进行排序,这总是需要首先收集它们), (...)
外壳不再是绝对必要的,但这可以被视为一个实现细节,因此为了概念清晰,最好继续使用(...)
。
[2] PowerShell's -replace
operator operates on regexes (regular expressions); [2] PowerShell 的
-replace
运算符对正则表达式(正则表达式)进行操作; it doesn't perform literal substring searches the way that the [string]
type's .Replace()
method does.它不会像
[string]
类型的.Replace()
方法那样执行文字子字符串搜索。
The below command will return ALL files from the current folder and sub-folders within the current directory the command is executed from.下面的命令将返回当前文件夹和执行命令的当前目录中的子文件夹中的所有文件。
Get-ChildItem -Recurse
Because of this you are also re-turning all the files you have already updated to have the _old suffix.因此,您还需要将已更新的所有文件重新设置为具有 _old 后缀。
What you need to do is use the -Include -Exclude paramters of the Get-Childitem Cmdlet in order to ignore files that already have the _old suffix, and meet your include criteria, for example.例如,您需要做的是使用 Get-Childitem Cmdlet 的 -Include -Exclude 参数来忽略已经具有 _old 后缀的文件,并满足您的包含条件。
Get-ChildItem -Recure -Include "*.txt" -Exclude "*_old"
Then pipe the results into your re-name item command然后将结果通过管道传输到您的重命名项目命令中
Get-ChildItem cmdlet explanation can be found here.可以在此处找到 Get-ChildItem cmdlet 说明。
https://docs.microsoft.com/en-us/powershell/module/microsoft.powershell.management/get-childitem?view=powershell-7 https://docs.microsoft.com/en-us/powershell/module/microsoft.powershell.management/get-childitem?view=powershell-7
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.