2013-10-02 25 views
1

我有一个包含数千个文件名的文件夹。Powershell中的文件和文件夹操作

所有文件名都是相对于用户的用户ID。有些用户在此文件夹中有多个文件,因此它会在名称的末尾附加一个数字。 I.E. susy.txt,susy1.txt,susy2.txt,carl.txt,carl1.txt等...

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

它甚至有可能做到这一点作为一个批处理文件,如果有的话可以有人指出我在这样做的正确方向吗?我在编写批处理脚本方面有少量知识,并希望以此为契机了解更多信息。

感谢

回答

3

这是一个更简单/更紧凑的方式:

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

一个纯粹的可能会说,这是“更好的做法”,以测试的路径尝试创建目录之前,但我一般喜欢更紧凑的代码;如果没有其他决定取决于该目录是否已经存在,那么只需每次尝试创建它并忽略错误会更快。


一对夫妇的注释,响应OP的评论:

  • ?{ }是简写位置对象,该过滤器上的条件,即只有符合特定条件对象传递给管道。所以在这种情况下,它采用当前目录的上市仅选择其名称属性的正则表达式匹配的对象。
  • 在使用-match运算符后,匹配将存储在自动数组变量$匹配$比赛[0]包含字符串的整个匹配部分和索引从1开始包含匹配组,从左边括号的顺序位置编号,即$匹配[1]被匹配组与开始第一左括号遇到,$比赛[2]与第二左括号开始比赛基等

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

+0

好吧,这个工作惊人的,只是如何我想它。谢谢!我显然不是一个PowerShell的专业人士,但我大部分都明白这一点......我只是不知道什么?{}的意思和$匹配[1]。主要是[1],我不明白。再次感谢你! – Johnrad

+0

再次感谢您!完美的感觉! – Johnrad

2

这里是我的快速和肮脏的,捏造的解决方案。它使用正则表达式将用户名从文件名中分离出来,即该表达式将从carl1.txtcarl3.txtcarl22.txt中拆分出carl。然后它会从这些名称中唯一地创建文件夹。所以它只尝试创建carl一次,而不是57次。之后,它将所有的carljohnnysusy等移动到新的文件夹中。

如果你是新的,不要害怕,如果这似乎有点恐吓。尤其是正则表达式如果没有它们,几乎可以肯定有一种方法可以做到这一点,如果它们让你感到困惑的话,但是正则表达式就是这些工具之一,一旦你了解它,你就会意识到它在解决问题上有多么伟大。

[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 
    } 
+0

+1 - 请注意,这会为用户创建一个目录,即使他们只有一个单一的文件,这是不是有什么OP要求。 – dugas

+0

同意。虽然它很可能他们想要的东西:P – EdgeVB

+0

一对夫妇的与正则表达式......不是主要的问题,但我不知道你为什么要写这样的说法。 (1)为什么正则表达式中'\ w'之后的'.'?尽管名称不会只有一个字符长,但OP没有指定至少两个字符。另外,为什么只要求第一个字符在\ w类中,并且在匹配任何字符之后,直到第一个数字或句点? –

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 } 

} 
相关问题