Строковая работа Powershell

Это мой первый вопрос здесь, и я новичок в powershell.

У меня есть папка $home\Devoluciones\ с несколькими файлами с именами DtoXXXYYYYMM.dat, где XXX — номер компании, YYYY — текущий год, а MM — текущий месяц.

Что мне нужно сделать, так это скопировать эти файлы в папки с номером компании, например, если у меня есть Dto509201506.dat и Dto908201506.dat, мне нужно скопировать эти файлы в $destination\509\ и $destination\908\ соответственно.

До сих пор у меня есть следующий код:

#List the items and send to a.txt
ls $home\Devoluciones\Dto*.dat | select -exp Name > $home\a.txt
#From a.txt keep first 6 characters and send to b.txt
Get-Content $home\a.txt | foreach {$_.remove(6)} | Add-Content $home\b.txt
#From b.txt replace Dto with "" and send to c.txt
Get-Content $home\b.txt | foreach {$_ -replace "Dto",""} | Add-Content $home\c.txt
#From c.txt copy the files to destination
Get-Content $home\c.txt | foreach {copy-item $home\Devoluciones\*$_*.dat $Destination\$_\}
#Clean temp files
Remove-Item -ErrorAction Ignore $home\a.txt -Force
Remove-Item -ErrorAction Ignore $home\b.txt -Force
Remove-Item -ErrorAction Ignore $home\c.txt -Force

Я хотел бы добиться того же результата, сделав его «чище», чем это, я хочу научиться манипулировать строкой в ​​​​одной строке и, если возможно, скопировать все с помощью одной команды.

Спасибо, Нестор.


person Nestoter    schedule 18.06.2015    source источник


Ответы (2)


Вот простая реализация, которая не требует пояснений. Я уверен, что кто-то также добавит более краткий однострочный ответ.

$Files = Get-Childitem -path "$home\Devoluciones\*" -include *.dat
foreach ($file in $files) {
    $company = $file.Name.Substring(3,3)
    copy-item $file.FullName (join-path (join-path $Destination $company) $file.Name)
}

РЕДАКТИРОВАТЬ: исправлена ​​ошибка в пути назначения

EDIT2: Get-ChildItem "Параметр Include действует, только если команда включает параметр Recurse или путь ведет к содержимому каталога, например C:\Windows*, где указан подстановочный знак"

person Jan Chrbolka    schedule 18.06.2015
comment
Я думаю, что двойные кавычки должны быть одинарными. В противном случае $home будет неправильно истолковано как имя переменной. - person Walter Mitty; 19.06.2015
comment
@WalterMitty это возможно, но я думаю, что в этом случае мы используем переменную $home. Мы хотим, чтобы это расширилось. - person Matt; 19.06.2015
comment
@Matt Спасибо за редактирование. Выполняет ли ‹!-- language: lang-psh --› подсветку синтаксиса для PowerShell? - person Jan Chrbolka; 19.06.2015
comment
Да и <!-- language: lang-powershell --> но пш короче :) - person Matt; 19.06.2015
comment
Ok. Мне не удалось понять, что $home предназначался как ссылка на переменную. - person Walter Mitty; 19.06.2015
comment
Мне нравится, завтра попробую. - person Nestoter; 22.06.2015
comment
Это не работает для меня. Я хотел бы понять, как это работает, чтобы найти обходной путь: вы определяете $Files как группу файлов. Затем вы делаете foreach ($file в $files) 1) Почему вы используете $files вместо $Files? Переменные Ps не чувствительны к регистру? Я добавил в foreach этот код, чтобы увидеть, что происходит: Write-Host $company Write-Host $file.FullName Но он ничего не пишет. 2) Что мне нужно сделать, чтобы вывести это переменное содержимое на экран? - person Nestoter; 23.06.2015
comment
@Nestoter Да, имена переменных PS не чувствительны к регистру, но рекомендуется все время использовать один и тот же регистр. Виноват. Write-Host — правильная команда, поэтому, если вы не получаете результатов, скорее всего, вы не получаете никаких файлов. Попробуйте просто $Files = Get-Childitem -path "a known directory here ...". Посмотрим, может ли это дать какие-то результаты. - person Jan Chrbolka; 23.06.2015
comment
@JanChrbolka Это сработало после удаления -включить *.dat Спасибо, Ян! - person Nestoter; 23.06.2015

Весь PowerShell можно записать в виде одной ужасной строки, если хотите, но вот что-то довольно краткое.

$path = "$home\Devoluciones\"
$destination = "C:\temp"
Get-ChildItem "$path\dto*.dat" | Copy-Item  -Destination {[System.IO.Path]::Combine($destination,($_.Name).Substring(3,3),$_.Name)} -Force

То, что это будет делать здесь, это именно то, что вы хотите. Возьмите все отфильтрованные файлы и для каждого скопируйте его в папку, соответствующую 3-6-му буквенному коду, содержащемуся внутри. Если папка назначения не существует, мы используем -Force для ее создания. Полезно для новых балансовых единиц. Мы используем [System.IO.Path]::Combine для создания целевого пути к файлу, который состоит из папки назначения, папки компании и текущего файла в канале.

person Matt    schedule 19.06.2015