我已经在互联网上搜寻了这个答案。也许就在这里,但是,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或类似的文件。
虽然原始作者相当一致,但发生了人为错误,因此,我想做的基本上是寻找“足够接近”。
我们可能有:
我想做的就是获取所有这些文件的文件结构,并将它们移到我的“ 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
}
答案 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
所以我只想要第一个索引值。我还想保持文件结构而不复制所有内容,因此我使用了分割路径来分解它。这是个大杂烩,看起来也不漂亮,但是可以。