1

我有一个包含数千个文件名的文件夹。

所有文件名都与用户的用户 ID 相关。某些用户在此文件夹中有多个文件,因此它会在名称的末尾附加一个数字。即 susy.txt、susy1.txt、susy2.txt、carl.txt、carl1.txt 等...

我想要做的是为每个拥有多个文件的用户创建一个特定的文件夹,并将所有关联的文件移动到该文件夹​​中。所以我注意到有多个 susy 文件。所以我想创建一个名为 Susy 的文件夹,并将 susy.txt、susy1.txt 和 susy2.txt 放入其中......所有文件都以此类推。

甚至可以将其作为批处理文件执行,如果可以的话,有人可以指出我这样做的正确方向吗?我对编写批处理脚本有少量的知识,并想以此为契机进一步了解。

谢谢

4

3 回答 3

3

这是一种更简单/更紧凑的方法:

Get-ChildItem | ?{$_.Name -match '(\D+)\d*\.txt'} | %{
  md $matches[1] -ea SilentlyContinue 
  Move-Item $_ $matches[1]
}

纯粹主义者可能会说在尝试创建目录之前对Test-Path进行“更好的实践”,但我通常更喜欢更紧凑的代码;如果没有其他决定取决于目录是否已经存在,那么每次尝试创建它并忽略错误会更快。


一些解释性说明,以回应 OP 的评论:

  • ?{ }Where-Object的简写,它根据条件进行过滤,即只有满足指定条件的对象才被传递到管道中。因此,在这种情况下,它获取当前目录的列表并仅选择其Name属性与正则表达式匹配的对象。
  • 使用-match运算符后,匹配项存储在自动数组变量$matches 中$matches[0]包含字符串的整个匹配部分,以 1 开头的索引包含匹配组,从左括号的序号位置开始编号,即$matches[1]是从第一个左括号开始的匹配组遇到,$matches[2]是从第二个左括号开始的匹配组,依此类推。

    在这种情况下,只有一个匹配组,$matches[1]包含匹配的字符串部分(\D+),即在第一个数字或点之前的连续非数字字符序列。

于 2013-10-03T03:36:27.910 回答
2

这是我刚刚捏造出来的快速而肮脏的解决方案。它使用正则表达式将用户名从文件名中拆分出来,即表达式将拆分carlcarl1.txt carl3.txt carl22.txt. 然后,它会根据这些名称创建唯一的文件夹。所以它只尝试创建carl一次,而不是 57 次。之后,它将所有carljohnny等移动susy到新文件夹中。

如果您是新手,如果这看起来有点吓人,请不要害怕。尤其是正则表达式。如果它们让您感到困惑,几乎可以肯定有一种方法可以在没有它们的情况下做到这一点,但是正则表达式是其中一种工具,一旦您学习了它,您就会意识到它在解决问题方面有多棒。

[regex]$pattern_name = '^\w.+?(?=[\d\.])'

# create folders for all the unique users
get-Childitem -File -path 'c:\scripts' | foreach-Object {$pattern_name.match($_).value } | sort -unique | foreach-Object { mkdir $_ }

# move files into those folders
get-Childitem -File -path 'c:\scripts' | foreach-Object {
    $user = $pattern_name.match($_).value 
    Move-Item -destination ".\$user" -Path $_.FullName
    }
于 2013-10-02T23:08:33.950 回答
0

一种方法。这是做什么的:

  1. 按用户名对目录中的文件进行分组。

  2. 如果该组有多个文件,它会为用户创建一个目录,然后将用户的文件移动到该目录中。

(请注意,我在所有会修改数据的命令中添加了 -WhatIf 选项 - 您必须删除它们才能实际修改数据。)

# Make backup for safety
cp -recurse .\userFiles .\userFilesBackup

cd .\userFiles

gci | `

select-object @{n='User';e={$_.BaseName -replace "^([a-z]+)[\d]*$", '$1'}}, Name | `

group-object User | `

? { $_.Count -gt 1 } | `

% { `

$userDirectory = $_.Name
mkdir -WhatIf $userDirectory

foreach ($f in $_.Group)
{ mv -WhatIf $f.Name $userDirectory }

}
于 2013-10-02T23:46:03.410 回答