3

This is my first question here and i'm new to powershell.

I have a folder $home\Devoluciones\ with several files named DtoXXXYYYYMM.dat where XXX is a company number, YYYY is the current year and MM stands for current month.

What i need to do is to copy those files to folders named with the company number, for example if i have Dto509201506.dat and Dto908201506.dat i need to copy those files to $destination\509\ and $destination\908\ respectively.

Till now i have the following code:

#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

I would like to achieve the same result doing it "cleaner" than this, i want to learn how to manipulate the string in one line and if is it possible copy all with only one command.

Thanks, Nestor.

Matt
  • 45,022
  • 8
  • 78
  • 119
Nestoter
  • 79
  • 9

2 Answers2

2

Here is a simple implementation that should be self explanatory. I'm sure somebody will add a more concise one line answer as well.

$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)
}

EDIT: Fixed error in destination path

EDIT2: Get-ChildItem "The Include parameter is effective only when the command includes the Recurse parameter or the path leads to the contents of a directory, such as C:\Windows*, where the wildcard character is specified"

Jan Chrbolka
  • 4,184
  • 2
  • 29
  • 38
  • I think the double quotes have to be single quotes. Otherwise $home will be misinterpred as the name of a variable. – Walter Mitty Jun 19 '15 at 00:00
  • @WalterMitty that is possible but I think in this case we are using the `$home` variable. We want that to expand. – Matt Jun 19 '15 at 00:03
  • @Matt Thanks for the edit. Does ** do the syntax highlight for PowerShell? – Jan Chrbolka Jun 19 '15 at 00:09
  • Yes and `` but psh is shorter :) – Matt Jun 19 '15 at 00:14
  • ok. I failed to get that $home was intended as a variable reference. – Walter Mitty Jun 19 '15 at 09:43
  • I like this, i'm gonna try it tomorrow. – Nestoter Jun 22 '15 at 01:02
  • This isn't working for me. I would like to understand how this work to find a workaround: You define $Files as a group of files. Then you do foreach ($file in $files) 1) Why you use $files instead of $Files? Ps variables are not case sensitive? I added inside the foreach this code to see what's happening: Write-Host $company Write-Host $file.FullName But it isn't writing anythig. 2) What i have to do to write thses variable content into screen? – Nestoter Jun 23 '15 at 00:08
  • @Nestoter Yes, PS variable names are not case sensitive, but it's good practice to use the same case all the time. My bad. Write-Host is the right command, so if you are not getting results, it's most likely that you are not getting any files in. Try just a simple `$Files = Get-Childitem -path "a known directory here ..."`. See if that can get some results. – Jan Chrbolka Jun 23 '15 at 00:31
  • @JanChrbolka It worked after remove -include *.dat Thank you Jan! – Nestoter Jun 23 '15 at 00:54
1

All PowerShell can be written as one awful line if you want it to be but here is something that is quite terse.

$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

What this will do here is exactly what you want. Take all the filtered files and for each one copy it to the folder that corresponds with the 3-6th letter code contained within. If the destination folder does not exist then we use -Force to make it. Helpful for new company codes. We use [System.IO.Path]::Combine to make the target file path which consists of the destination folder, company folder and current file in the pipe.

Matt
  • 45,022
  • 8
  • 78
  • 119