在Powershell中搜索文件

时间:2018-06-21 17:46:31

标签: powershell

我已经在互联网上搜寻了这个答案。也许就在这里,但是,las,我没时间了,我们的时间表是在法律上吸引优秀男生的时间。

我们有一些文件需要根据出现在目录路径中的特定名称进行检索。

存储和保存所有这些文件的人始终保持相同的命名约定。她非常棒,对她来说也+++。

文件结构如下:

Animals
       -Dogs
            -Folders With Breeds of Dogs
                     -<Breed of Dog>_MA_etc.pdf
       -Cats
            -Folders with Breeds of Cats
                     -<Breed of Cat>_MA_etc.pdf
       -ETC
            -etc
                -etc

保存文件的人对文件结构和命名约定一丝不苟,因此您可以期望使用c:\​​ animals \ dogs \ GSD \ GSD_MA.PDF或类似的文件。

虽然原始作者相当一致,但发生了人为错误,因此,我想做的基本上是寻找“足够接近”。

我们可能有:

  • 客户协议\ Netflix \文件
  • 主协议\ Netflix,Inc \文件
  • 租赁协议\ Netflix \文件

我想做的就是获取所有这些文件的文件结构,并将它们移到我的“ E:\ sorted”目录中,以保持文件结构。

因此,从动物开始,我们从合法的客户名单中获得了他们感兴趣的名称。如果我寻找name:name,我会得到27个结果。到目前为止还不好。

我尝试了部分操作,但结果为零。所以这是我下面的糟糕代码。也许你可以取笑我,告诉我我哪里出了问题。

$a = Import-CSV C:\scripts\Clients.csv
$a = @($a.Client)
#$a = $a | %{ $_.SubString(0,6) }

$c = Get-ChildItem E:\Legal\ -include ($a) -recurse # | Where-Object {($_ -match $a)}


ForEach($file in $c){
    $dest =  Split-Path -path $file.FullName -Parent | Split-path -NoQualifier
    #Copy-Item -path $file -recurse -Destination "e:\sorted\11\$dest" -force -Verbose
}

3 个答案:

答案 0 :(得分:1)

我希望可以使用更多类似于PowerShell的方法,但是我使用了更具过程性的方法。

使用HashSet,创建一组需要复制的目录。 HashSet只有一个条目,因此,如果它包含“ C:\ A \ B”,那么再次添加“ C:\ A \ B”将不会添加另一个条目。

.contains方法是.NET,而不是PS方法,对于.replace也是类似。

$src = "C:\temp\a"
$dest = "F:\temp\b"

$CsvFile = Join-Path -Path $src -ChildPath "findthese.csv"
$sought = (Import-Csv $CsvFile).Client
$dirs = Get-ChildItem -Path $src -Directory -Recurse

$set = New-Object System.Collections.Generic.HashSet[string]

# get the directories with a client name in the path anywhere
foreach($dir in $dirs) {
    foreach($client in $sought) {
        if ($dir.FullName.contains($client)) {
           $temp = $set.Add($dir.FullName)
        }
    }
}

# copy the selected directory structures to the destination
foreach($dir in $set) {
    Copy-Item -path $dir -Destination $dir.replace($src, $dest) -Recurse -WhatIf
}

我将-WhatIf留在了那里,因此您可以快速检查它会做正确的事。

答案 1 :(得分:0)

如果$a中的名称与文件名不完全匹配,将其用作include参数的输入将无法帮助您找到所需的文件。

我有一个名为clients.csv的follwong文件

client,gender,fun
fred,m,y
barney,m,y  
wilma,f,y
navneet,n,y
kumar,f,y
konda,m,y

在当前目录中,我有一个名为clients的目录,其中包含以下内容:

C:
├───clients
    ├───losers
    │       barney_loser.txt
    │       kumar_loser.txt
    │
    └───winners
            fred_winner.txt
            konda_winner.txt
            wilma_winner.txt

案例1:

ls .\clients\ -Filter *.txt -Recurse

返回所有文本文件。

情况2:

$people = import-csv -path .\people.csv
$clients = $people.client
ls .\clients\ -Filter *.txt -Recurse -Include $clients

什么也没回报。

案例3:

$people = import-csv -path .\people.csv
$clients = $people.client
$clients += 'kumar_loser.txt'
ls .\clients\ -Filter *.txt -Recurse -Include $clients

为我返回了“ kumar_loser.txt”的一条记录。

我断言您列表($a)中的模式与文件名不匹配。

如果我想在示例中修复该问题,可以执行以下操作...

$people = import-csv -path .\people.csv
$clients = $people.client
for($i = 0; $i -lt $clients.length; $i++) {
  $clients[$i] = '*{0}*' -f $clients[$i]
}
ls .\clients\ -Filter *.txt -Recurse -Include $clients

希望这会有所帮助。

答案 2 :(得分:0)

感谢帮助人员。

如上所述,我采用了较少的脚本化方法和程序性方法。这是我使用的代码,主要是,一位同事,我仔细检查了结果并验证了一些异常文件。我必须仔细检查弹出的错误,并找到了我想要的其他文件。并非完美,但绝对可以减少700个文件夹和3000个文件的查找。 include很棒,但是过滤器是我真正想要的。此外,Include不喜欢索引值,而Filter特别不喜欢,因此我不得不将其保存到变量中,并使用*通配符进行过滤,该通配符 did 起作用。

这就是我所做的:

$people = Import-CSV C:\scripts\HelenClients.csv
$clients = $people.Client| %{$_.SubString(0,5)}


for($i=0; $i -lt $clients.Length; $i++){
    $name = $clients[$i]
    Write-Host "Searching for $name"
    $file = Get-ChildItem 'E:\Legal\' -Include "$name*" -recurse
    if($file -ne $null){
        $dest = Split-Path -path $file -Parent
        $dest1 = $dest | Split-Path -NoQualifier
        $from = $dest[0]
        $to = $dest1[0]
        $too = $file.BaseName[0]
        Copy-Item $file -Destination e:\sorted\16\$to\$too\ -force -Verbose
    }
    else{
        Write-Output "No results found"
    }
}

当您将结果存储到变量中时,我发现,如果有多个变量,它将列出所有位置和名称,等等。不漂亮。见下文:

PS C:\Users\me> $ff


    Directory: E:\ParentDir\subfolder\redacted


Mode                LastWriteTime         Length Name                                                                                                                                                                                    
----                -------------         ------ ----                                                                                                                                                                                    
-a----         6/4/2018   1:47 PM          50485 redacted.docx                                                                                                                           
-a----         6/4/2018   1:47 PM         155579 redacted.pdf                                                                                                                            



PS C:\Users\me> $ff.Basename
Redacted Basename 0
Redacted Basename 1

PS C:\Users\me> $ff.BaseName[0]
Redacted Basename 0

所以我只想要第一个索引值。我还想保持文件结构而不复制所有内容,因此我使用了分割路径来分解它。这是个大杂烩,看起来也不漂亮,但是可以。