I am trying to build a script that can do the following
When I open the powershell script
it should ask me for a path where the files are located e.g.
C:\SearchPath\DateOfToday
Daily there will be a new folder e.g. 20221214.
Maybe it is possible to specify the path and the script will get today's date by itself or maybe just opening a windows explorer so I can select the SourceFolder.
A file must be copied e.g. Test.xmr and then renamed to Test.$xmr
some more files should be collected like
jpl, eml, html, pdf, cml, xmr, $xmr and xml
the collected files should be moved to the folder
C:\AnotherFolder\
What I have so far is this
$SourceFolder = "\\Path1\Dateoftoday"
$DestFolder = '\\Path2' #Path to Destination Folder
[array]$FileList = gci -Path $SourceFolder -Recurse -File -Filter "ABC.xmr"
[array]$FileList = gci -Path $SourceFolder -Recurse -File -Filter "ABC.jpl"
[array]$FileList = gci -Path $SourceFolder -Recurse -File -Filter "ABC.eml"
[array]$FileList = gci -Path $SourceFolder -Recurse -File -Filter "ABC.html"
[array]$FileList = gci -Path $SourceFolder -Recurse -File -Filter "ABC.pdf"
[array]$FileList = gci -Path $SourceFolder -Recurse -File -Filter "ABC.cml"
[array]$FileList = gci -Path $SourceFolder -Recurse -File -Filter "ABC.xml"
ForEach ($F in $FileList) {
Copy-Item $F.FullName (Join-Path $DestFolder ($F.Name))
}
I can specify the path and the filenames and then run it.
Sorry if it's basic, but I'm new at powershell.
Looks like you just need this:
$today = '{0:yyyyMMdd}' -f (Get-Date)
$SourceFolder = "\\Path1\$today"
$DestFolder = '\\Path2' #Path to Destination Folder
$filePattern = '*.xmr', '*.jpl', '*.eml', '*.html', '*.pdf', '*.cml', '*.xml', '*.$xmr'
# unclear about your question 2)..
# do we need to copy a file to the $SourceFolder first ??
# Copy-Item -Path 'X:\Somewhere\Test.xmr' -Destination (Join-Path -Path $SourceFolder -ChildPath 'Test.$xmr')
# copy all chosen files to the destination folder
Get-ChildItem -LiteralPath $SourceFolder -Recurse -File -Include $filePattern | ForEach-Object {
$_ | Copy-Item -Destination $DestFolder
}
As per your comment, hopefully this is what you need:
$today = '{0:yyyyMMdd}' -f (Get-Date)
$SourceFolder = "\\Path1\$today"
$DestFolder = '\\Path2' #Path to Destination Folder
$extensions = 'xmr', 'jpl', 'eml', 'html', 'pdf', 'cml', 'xml'
# ask for the filename
$baseName = Read-Host 'Please enter the file name without extension'
if (![string]::IsNullOrWhiteSpace($baseName)) {
# construct the filenames to copy
$pattern = $extensions | ForEach-Object { '{0}.{1}' -f $baseName.Trim(), $_ }
# copy all chosen files to the destination folder
Get-ChildItem -LiteralPath $SourceFolder -Recurse -File |
Where-Object { $pattern -contains $_.Name } | ForEach-Object {
# rename the extensions by prefixing it with a dollar sign ($)
$targetFile = Join-Path -Path $DestFolder -ChildPath ('{0}.${1}' -f $_.BaseName, $_.Extension.TrimStart("."))
$_ | Copy-Item -Destination $targetFile
# if you want ONLY the .xmr file to be renamed with as .$xmr use this instead:
# if ($_.Extension -eq '.xmr') {
# $targetFile = Join-Path -Path $DestFolder -ChildPath ('{0}.${1}' -f $_.BaseName, $_.Extension.TrimStart("."))
# $_ | Copy-Item -Destination $targetFile
# }
# else {
# $_ | Copy-Item -Destination $DestFolder
# }
}
}
Edit
As you commentd you want to remove the leftover .xmr and .att files after copying, here the code that does that too
$today = '{0:yyyyMMdd}' -f (Get-Date)
$SourceFolder = "\\Path1\$today"
$DestFolder = '\\Path2' #Path to Destination Folder
$extensions = 'xmr', 'jpl', 'eml', 'html', 'pdf', 'cml', 'xml', 'att'
# ask for the filename
$baseName = Read-Host 'Please enter the file name without extension'
if (![string]::IsNullOrWhiteSpace($baseName)) {
# construct the filenames to copy
$pattern = $extensions | ForEach-Object { '{0}.{1}' -f $baseName.Trim(), $_ }
# copy all chosen files to the destination folder
(Get-ChildItem -LiteralPath $SourceFolder -Recurse -File) |
Where-Object { $pattern -contains $_.Name } | ForEach-Object {
# rename the extensions by prefixing it with a dollar sign ($)
$targetFile = Join-Path -Path $DestFolder -ChildPath ('{0}.${1}' -f $_.BaseName, $_.Extension.TrimStart("."))
$_ | Copy-Item -Destination $targetFile
# if you want ONLY the .xmr file to be renamed with as .$xmr use this instead:
# if ($_.Extension -eq '.xmr') {
# $targetFile = Join-Path -Path $DestFolder -ChildPath ('{0}.${1}' -f $_.BaseName, $_.Extension.TrimStart("."))
# $_ | Copy-Item -Destination $targetFile
# }
# else {
# $_ | Copy-Item -Destination $DestFolder
# }
# remove leftover .XMR and .ATT files
if ($_.Extension -match '\.(xmr|att)$') { $_ | Remove-Item -Force }
}
}
Good day!!
Maybe we can help you with this:
First of all you need to ask for the path and we have two ways to do this (maybe more) but those are the ways I know
The first option is the simple, using the Read-Host Cmdlet:
$path = Read-Host "Please type the path of the folder"
The second option is more complicated and use dotnet framework: (to ask for the destination just change the last two variables with destination instead of sourcePath)
Add-Type -AssemblyName System.Windows.Forms
Add-Type -AssemblyName System.Drawing
$box = New-Object System.Windows.Forms.Form
$box.Text = 'Script Execution'
$box.Size = New-Object System.Drawing.Size(300,200)
$box.StartPosition = 'CenterScreen'
$okButton = New-Object System.Windows.Forms.Button
$okButton.Location = New-Object System.Drawing.Point(75,120)
$okButton.Size = New-Object System.Drawing.Size(75,23)
$okButton.Text = 'OK'
$okButton.DialogResult = [System.Windows.Forms.DialogResult]::OK
$box.AcceptButton = $okButton
$box.Controls.Add($okButton)
$cancelButton = New-Object System.Windows.Forms.Button
$cancelButton.Location = New-Object System.Drawing.Point(150,120)
$cancelButton.Size = New-Object System.Drawing.Size(75,23)
$cancelButton.Text = 'Cancel'
$cancelButton.DialogResult = [System.Windows.Forms.DialogResult]::Cancel
$box.CancelButton = $cancelButton
$box.Controls.Add($cancelButton)
$label = New-Object System.Windows.Forms.Label
$label.Location = New-Object System.Drawing.Point(10,20)
$label.Size = New-Object System.Drawing.Size(280,20)
$label.Text = 'Please type the path of the files:'
$box.Controls.Add($label)
$textBox = New-Object System.Windows.Forms.TextBox
$textBox.Location = New-Object System.Drawing.Point(10,40)
$textBox.Size = New-Object System.Drawing.Size(260,20)
$box.Controls.Add($textBox)
$box.Topmost = $true
$box.Add_Shown({$textBox.Select()})
$result = $box.ShowDialog()
if ($result -eq [System.Windows.Forms.DialogResult]::OK)
{
$sourcePath = $textBox.Text
$sourcePath
}
Once we have the path we can copy the files to do it we can use Copy-item
(I'm not sure if you want to rename the original files or the final files, anyway if you want to rename the last files just use rename-item cmdlet)
$fileList = #(
Get-ChildItem -Path $sourcePath -Recurse -include "*.jpl", "*.eml", "*.html", "*.pdf", "*.cml", "*.xml"
)
foreach ($f in $fileList){
Copy-Item -Path $f.fullname -Destination "$destPath\$f.name"
}
And this should be enough, i'm not really sure about the $fileList part maybe I made some typo, sorry in this case.
Have a nice day!
Related
Apologies, this question is scattered on the internet but I have yet to find a satisfactory answer that uses only Powershell 2.0 (with .NET v3.5) - no external libraries or programs
I'm using the following code to extract log.txt from ZipFile.zip (no matter log.txt's location)
$Destination = (new-object -com shell.application).NameSpace('C:\ZipExtractDir')
$ZipFile = (new-object -com shell.application).NameSpace('C:\ZipFile.zip')
$Destination.CopyHere(($Zipfile.Items() | where-object {$_.Name -like '*log.txt'}), 1044)
Works if log.txt is in directory root \log.txt
Fails if log.txt is in a subdirectory \Subfolder\log.txt
Fails if referencing the literal (.zip) path
{$_.Name -Like '*Subfolder\log.txt'} (both double & single quotes fail)
Have tried using -eq -like -contains '' "" $_.FullName
I'm quite certain that I'm filtering incorrectly - can anyone help with this code so that it will parse subdirectories as well?
Similar to what you have already done, you can set up the Shell.Application namespaces like this. Then you can copy the extracted directory to the destination path.
$zipFilePath = "Zipfile.zip"
$destinationPath = "C:\Users\Public\Downloads"
$zipfile = (New-Object -Com Shell.Application).NameSpace($zipFilePath)
$destination = (New-Object -Com Shell.Application).NameSpace($destinationPath)
$destination.CopyHere($zipfile.Items())
Then to list the log.txt files, we can contruct the full extracted path with Join-Path. This basically just appends the zip file name from System.IO.Path.GetFileNameWithoutExtension() to the destination path. Then just use Get-ChildItem to list the files recursively with the -Recurse and -Filter switches.
$extractedPath = Join-Path -Path $destinationPath -ChildPath ([System.IO.Path]::GetFileNameWithoutExtension($zipFilePath))
Get-ChildItem -Path $extractedPath -Filter log.txt -Recurse
And to test this for PowerShell 2.0 we can use -version 2 with powershell.exe:
powershell.exe -version 2 .\test.ps1
UPDATE
If you want to inspect files before extracting, you'll need to recurse the directories yourself. Below is a demo of how this can be done.
function New-ZipChildRootFolder
{
param
(
[string]$DestinationPath,
[string]$ZipFileName
)
$folderPath = Split-Path -Path $ZipFileName -Leaf
$destination = (New-Object -ComObject Shell.Application).NameSpace($DestinationPath)
$destination.NewFolder($folderPath)
}
function Get-ZipChildItems
{
param
(
[string]$ZipFilePath,
[string]$DestinationPath
)
$zipfile = (New-Object -ComObject Shell.Application).NameSpace($ZipFilePath)
$zipFileName = [System.IO.Path]::GetFileNameWithoutExtension($ZipFilePath)
Write-Output "Create root zip folder : $zipFileName"
New-ZipChildRootFolder -DestinationPath $DestinationPath -ZipFileName $zipFileName
foreach ($item in $zipFile.items())
{
Get-ZipChildItemsRecurse -Items $item -DestinationPath $DestinationPath -ZipFileName $zipFileName
}
}
function Get-ZipChildItemsRecurse
{
param
(
[object]$Items,
[string]$DestinationPath,
[string]$ZipFileName
)
foreach ($file in $Items.getFolder.Items())
{
if ($file.IsFolder -eq $true)
{
Write-Output "Creating folder : $($file.Path)"
New-ZipChildFolder -Folder $file -DestinationPath $DestinationPath -ZipFileName $ZipFileName
Get-ZipChildItemsRecurse -Items $file -DestinationPath $DestinationPath -ZipFileName $ZipFileName
}
else
{
$filename = Split-Path -Path $file.Path -Leaf
if ($filename -eq "log.txt")
{
Write-Output "Copying file : $($file.Path)"
New-ZipChildFile -File $file -DestinationPath $DestinationPath -ZipFileName $ZipFileName
}
}
}
}
function New-ZipChildFile
{
param
(
[object]$File,
[string]$DestinationPath,
[string]$ZipFileName
)
$destination = New-Object -ComObject Shell.Application
$items = $File.Path.Split("\")
$zipRootIndex = [array]::IndexOf($items, $ZipFileName)
$path = $items[$zipRootIndex..($items.Length - 2)] -join "\"
$fullPath = Join-path -Path $DestinationPath -ChildPath $path
$destination.NameSpace($fullPath).CopyHere($File)
}
function New-ZipChildFolder
{
param
(
[object]$Folder,
[string]$DestinationPath,
[string]$ZipFileName
)
$destination = New-Object -ComObject Shell.Application
$items = $Folder.Path.Split("\")
$zipRootIndex = [array]::IndexOf($items, $ZipFileName)
$folders = $items[$zipRootIndex..($items.Length - 1)]
$currentFolder = $DestinationPath
foreach ($folder in $folders)
{
$destination.NameSpace($currentFolder).NewFolder($folder)
$currentFolder = Join-Path -Path $currentFolder -ChildPath $folder
}
}
Usage:
$zipFilePath = "C:\Zipfile.zip"
$destinationPath = "C:\Users\Public\Downloads"
Get-ZipChildItems -ZipFile $zipFilePath -DestinationPath $destinationPath
I have a PowerShell script that moves all files from one location to another that have a date modified older than 3 years. I have it so the file when moved to the new location also keeps the file structure of the original.
I am trying to make it so once the file has been moved to the new location it creates a shortcut in the original directory which points to the new location of the file.
Below is my script so far which does all the above minus the shortcut.
$sourceDir = "C:\Users\bgough\Documents\powershell\docs"
$archiveTarget = "C:\Users\bgough\Documents\archive"
$dateToday = Get-Date
$date = $dateToday.AddYears(-3)
$items = Get-ChildItem $sourceDir -Recurse |
Where-Object {!$_.PSIsContainer -and $_.LastWriteTime -le $date}
foreach ($item in $items)
{
$withoutRoot = $item.FullName.Substring([System.IO.Path]::GetPathRoot($item.FullName).Length);
$destination = Join-Path -Path $archiveTarget -ChildPath $withoutRoot
$dir = Split-Path $destination
if (!(Test-Path $dir))
{
mkdir $dir
}
Move-Item -Path $item.FullName -Destination $destination
$WshShell = New-Object -ComObject WScript.Shell
$Shortcut = $WshShell.CreateShortcut("$sourceDir")
$Shortcut.TargetPath = $destination
$Shortcut.Save()
}
In my script I have included my attempt at creating this shortcut but it hasn't helped. I have also read through the following but don't understand it too well..
How to create a shortcut using Powershell
Powershell Hard and Soft Links
Edit:
I have successfully got the shortcut to create and in the original folder. However, I can't seem to figure out how to pass a variable to use as the shortcut name. At the moment a string is hard coded, which is what the shortcut gets named. Please see code below: I would like to set the name as the item full name (Same name as document that was moved).
$sourceDir = "C:\Users\bgough\Documents\powershell\docs"
$archiveTarget = "C:\Users\bgough\Documents\archive"
$dateToday = Get-Date
$date = $dateToday.AddYears(-3)
$items = Get-ChildItem $sourceDir -recurse | Where-Object {!$_.PsIsContainer -and $_.LastWriteTime -le $date}
foreach ($item in $items)
{
$withoutRoot = $item.FullName.Substring([System.IO.Path]::GetPathRoot($item.FullName).Length);
$destination = Join-Path -Path $archiveTarget -ChildPath $withoutRoot
$dir = Split-Path $destination
if (!(Test-Path $dir))
{
mkdir $dir
}
Move-Item -Path $item.FullName -Destination $destination
$wshshell = New-Object -ComObject WScript.Shell
$desktop = [System.Environment]::GetFolderPath('Desktop')
$lnk = $wshshell.CreateShortcut($sourceDir + "\ShortcutName.lnk")
$lnk.TargetPath = "$destination"
$lnk.Save()
}
.lnk files are fine when you're using Explorer but they don't play well in Powershell or a command prompt.
What you need to do is create a symbolic link for the file. You can't do this in Powershell, but there is a command line utility called mklink that does it. I've wrapped it in a function so that you can call it:
function CreateLink
{
param
(
[string] $LinkName,
[string] $TargetFile
)
&"cmd.exe" /c mklink "$LinkName" "$TargetFile" | Out-Null
}
In your example you would call it like this:
CreateLink -LinkName $item.FullName -TargetFile $destination
When you look at the directory in Powershell the file will show up as being 0 bytes in size. Don't worry about that.
Thanks for your script Android Magic.
I have modified it to:
Copy a set of files from source to destination
It creates the identical folder structure on the destination, even if the folders are empty
It then creates a symbolic link to the archived file. SymbolicLink support was added in Powershell v5.1. You have to run the script as Admin in order for the Symbolic Link creation to work.
I'd like to add a function to email if anything goes wrong and a summary of status, but that's for another day.
$sourceDir = "\\Fileserver1\IT\Vendor"
$archiveTarget = "\\FS-ARCHIVE\Archive\Fileserver1\IT\Vendor"
$rootArchivePath = "\\FS-ARCHIVE\Archive"
$dateToday = Get-Date
$date = $dateToday.AddYears(-3)
# Copy folder structure to Archive
Get-ChildItem -Path $sourceDir -Recurse |
?{ $_.PSIsContainer } |
Copy-Item -Destination {Join-Path $archiveTarget $_.Parent.FullName.Substring($sourceDir.length)} -Force
$items = Get-ChildItem $sourceDir -Recurse -Attributes !Directory |
Where-Object {$_.LastAccessTime -le $date}
foreach ($item in $items)
{
$withoutRoot = Split-Path -Path $item.FullName
$destination = $rootArchivePath + $withoutRoot.Remove(0,1)
$destFile = $destination + "\" + $item
Move-Item -Force -Path $item.FullName -Destination $destination -Verbose
New-Item -ItemType SymbolicLink -Path $withoutRoot -Name $item -Value $destFile -Force -Verbose
}
How do I get this powershell program to successfully execute?
$Source = "\\ahs-bind01\ftptest01\CRAR"
Get-ChildItem -Path $Source -recurse
#Declare the file path and sheet name
$file = "C:\Users\us6205\Desktop\DatabaseNameConfigs\Test\CareMoveFileParentDestPaths.xlsx"
$sheetName = "sheet1"
#Create an instance of Excel.Application and Open Excel file
$objExcel = New-Object -ComObject Excel.Application
$workbook = $objExcel.Workbooks.Open($file)
$sheet = $workbook.Worksheets.Item($sheetName)
$objExcel.Visible=$false
#Count max row
$rowMax = ($sheet.UsedRange.Rows).count
#Declare the starting positions
$rowLOC,$colLOC = 1,1
$rowUNC,$colUNC = 1,2
#loop to get values and store it
for ($i=1; $i -le $rowMax-1; $i++)
{
$LOC = $sheet.Cells.Item($rowLOC+$i,$colLOC).text
$UNC = $sheet.Cells.Item($rowUNC+$i,$colUNC).text
$Path = Get-ChildItem -Path $UNC -recurse |
Where-Object { ($_.PSIsContainer -eq $true) -and ( $_.FullName -match "$Source") }
$Dest = $Path | New-Item -path $Dest -itemtype directory | Move-Item -Path $Source -Destination $Dest -Force
}
#close excel file
$objExcel.quit()
You want to put these $Source = "\ahs-bind01\ftptest01\CRAR" Get-ChildItem -Path $Source -recurse each to its line like this:
$Source = "\ahs-bind01\ftptest01\CRAR"
Get-ChildItem -Path $Source -recurse
Same with $rowLOC,$colLOC = 1,1 $rowUNC,$colUNC = 1,2
$rowLOC,$colLOC = 1,1
$rowUNC,$colUNC = 1,2
Same with $LOC = $sheet.Cells.Item($rowLOC+$i,$colLOC).text $UNC = $sheet.Cells.Item($rowUNC+$i,$colUNC).text
$LOC = $sheet.Cells.Item($rowLOC+$i,$colLOC).text
$UNC = $sheet.Cells.Item($rowUNC+$i,$colUNC).text
Also edit ($.PSIsContainer -eq $true) -and ( $.FullName -match "$Source") to:
($_.PSIsContainer -eq $true) -and ( $_.FullName -match "$Source")
I added in New-Item command but it's not liking my syntax. Please help:
$Dir = get-childitem -path "\\ahs-bind01\ftptest01\CRAR" -recurse
$Source = $Dir | where {$_.extension -eq ".txt"}
#Declare the file path and sheet name
$file = "C:\Users\us6205\Desktop\DatabaseNameConfigs\Test\CareMoveFileParentDestPaths.xlsx"
$sheetName = "sheet1"
#Create an instance of Excel.Application and Open Excel file
$objExcel = New-Object -ComObject Excel.Application
$workbook = $objExcel.Workbooks.Open($file)
$sheet = $workbook.Worksheets.Item($sheetName)
$objExcel.Visible=$false
#Count max row
$rowMax = ($sheet.UsedRange.Rows).count
#Declare the starting positions
$rowLOC,$colLOC = 1,1
$rowUNC,$colUNC = 1,2
#loop to get values and store it
for ($i=1; $i -le $rowMax-1; $i++)
{
$LOC = $sheet.Cells.Item($rowLOC+$i,$colLOC).text
$UNC = $sheet.Cells.Item($rowUNC+$i,$colUNC).text
$Path = Get-ChildItem $UNC -recurse |
Where-Object { ($_.PSIsContainer -eq $true) -and ( $_.Name -match "$Source") }
$Dest = $Path | New-Item -path $Dest -itemtype directory | Move-Item -Path $Source -Destination $Dest -Force
}
#close excel file
$objExcel.quit()
Excel Doc:
Col A Col B
Test C:\Users\US6205\Desktop\Test\Unprocessed
Test1 C:\Users\US6205\Desktop\Test1\Unprocessed
The use of pipeline is not correct in below line:
$Dest = $Path | New-Item -path $Dest -itemtype directory | Move-Item -Path $Source -Destination $Dest -Force
This does not assign $Path to $Dest. It passes the $Path variable to next command on the right of the pipeline. $Dest is empty when you are trying to use in New-Item command. Instead, use in separate lines as below:
$Dest = $Path
New-Item -path $Dest -itemtype directory
Move-Item -Path $Source -Destination $Dest -Force
I would also recommend to use Test-Path cmdlet to check that the paths exist in your script.
I searched, i googled.. about to smash my head on the table
how come this will not work?
move-Item $path$file $targetdir
it gives me an error
Move-Item : An object at the specified path C:\Repository\test.csv
does not exist.
now if i debug this and i output using
write-output move-Item $path$file $targetdir
and take that output and paste it (file name with path and destination) it works!
and trust me the file is there. =\
Code below
$path = 'C:\test\'
$TimeStamp = Get-Date -Format "MM-dd-yyyy_hh-mm-ss"
$LogFile = Get-Date -Format "MM_dd_yyyy"
$targetdir = "C:\test\Uploaded\"
#Get-ChildItem -path $path\* -Include *.csv | foreach-object {$_.Fullname} | Format-Table name -hidetableheaders | Out-File $path\list.txt
Get-ChildItem -path $path\* -Include *.csv | Format-Table name -hidetableheaders | Out-File $path\list2.txt
get-content C:\test\list2.txt | where {$_ -ne ""} | out-file C:\test\list.txt
Remove-Item C:\test\list2.txt
$list = get-content C:\test\list.txt
foreach ($file in $list)
{
$ftp = "ftp://REMOVED/$file"
"ftp url: $ftp"
$webclient = New-Object System.Net.WebClient
$uri = New-Object System.Uri($ftp)
"Uploading $file..."
$succeeded = $true;
& {
trap { $script:succeeded = $false; continue }
$webclient.UploadFile($uri, $path+$file)
}
if ($succeeded)
{
echo $file 'Was successfully uploaded!' $Timestamp >> logfile$LogFile.log
move-Item -path $path$file -destination $targetdir
#test-path $path$file
}
else
{
echo $file 'Was not successfully uploaded, will retry later' $Timestamp >> logfile$LogFile.log
}
}
exit
Basics are:
Test-Path before you move it (file and destination)
Move the file, ensure you have permission (force it to move)
so:
echo $targetdir
echo "$path$file"
if (!(Test-Path $targetdir)) {
New-Item -ItemType directory $targetdir
}
if(Test-Path "$path$file") {
Move-Item "$path$file" $targetdir -Force
} else {
echo "file does not exist"
}
If you loop over a collection you have to use the ".FullName" property of the object:
Get-ChildItem $path | ForEach-Object { Move-Item $_.FullName $targetdir -Force }
Does the target directory already exist? I believe Move-Item will fail if the target directory doesn't exist. If that's the case, you can simply test for existence of the directory beforehand and then create as necessary.
If (!(Test-Path -Path $targetdir)) {
New-Item -ItemType directory -Path $targetdir
}
This worked for me. Thank you #TheMadTechnician. Hopes this helps everyone
$TimeStamp = Get-Date -Format "MM-dd-yyyy_hh-mm-ss"
$LogFile = Get-Date -Format "MM_dd_yyyy"
$path='C:\test\'
$targetDir = 'C:\test\Uploaded\'
$fileList = Get-ChildItem $path*.csv
If(!(Test-Path $TargetDir)){New-Item -ItemType Directory -Path $TargetDir|Out-Null}
$fileList | Select -ExpandProperty Name | Out-File 'C:\test\list.txt'
$list = get-content C:\test\list.txt
foreach ($file in $list)
{
$ftp = "ftp://REMOVED/$file"
"ftp url: $ftp"
$webclient = New-Object System.Net.WebClient
$uri = New-Object System.Uri($ftp)
"Uploading $file..."
$succeeded = $true;
& {
trap { $script:succeeded = $false; continue }
$webclient.UploadFile($uri, $path+$file)
}
if ($succeeded)
{
echo $file 'Was successfully uploaded!' $Timestamp >> logfile$LogFile.log
move-Item -path $path$file -destination $targetdir$Timestamp"_"$file
#test-path $path$file
}
else
{
echo $file 'Was not successfully uploaded, will retry later' $Timestamp >> logfile$LogFile.log
}
}
exit
How about this then:
ForEach($File in $List){
Join-Path $path $file | Move-Item -Dest $Targetdir
}
Edit: Also... your creation of list.txt, it bothered me so I had to comment. Format-Table should be used for formatting text, not for selecting a value to output to a file. There's a better way to do that, consider this alternative:
Get-ChildItem "$path*.csv" | Select -ExpandProperty Name | Out-File $pathlist.txt
Since you say that $path = 'C:\test\' you are adding extra backslashes in there that may cause issues for some commands.
Edit2: Ok, if that doesn't work, why not work with the files themselves instead of outputting to a file, importing from that file, and then working with things.
$path='c:\test\'
$TargetDir = 'c:\test\NewDir'
$FileList = Get-ChildItem $path*.csv
If(!(Test-Path $TargetDir)){New-Item -ItemType Directory -Path $TargetDir|Out-Null}
$FileList | Move-Item -Destination $TargetDir
Then if you really want a list of those file names just pipe $FileList to Select and then to Out-File
$FileList | Select -ExpandProperty Name | Out-File 'C:\Test\list.txt'
Here, look through this and see if there's anything you like. I made a few changes, such as declaring paths at the beginning for everything, I moved the WebClient object creation outside of the loop, and changed how things are displayed on screen. Plus I skip the entire exporting to text file and re-importing it.
$path = 'C:\test'
$ftpaddr = 'ftp://ftp.example.com/uploads'
$TimeStamp = Get-Date -Format "MM/dd/yyyy hh:mm:ss tt"
$LogFile = Get-Date -Format "MM_dd_yyyy"
$LogDir = "C:\Test\Logs"
If(!(test-path $LogDir)){New-Item -ItemType Directory -Path $LogDir | Out-Null}
$targetdir = 'C:\test\Uploaded'
If(!(test-path $targetdir)){New-Item -ItemType Directory -Path $targetdir | Out-Null}
$list = Get-ChildItem -path $path\* -Include *.csv
$webclient = New-Object System.Net.WebClient
"ftp url: $ftpaddr"
foreach ($file in ($list|select -ExpandProperty Name))
{
$uri = New-Object System.Uri(("$ftpaddr/$file"))
Write-Host "Uploading $file... " -NoNewline -ForegroundColor White
$succeeded = $true
& {
trap { $script:succeeded = $false; continue }
$webclient.UploadFile($uri, "$Path\$file")
}
if ($succeeded)
{
Write-Host "Success!" -ForegroundColor Green
"$Timestamp`t$File was successfully uploaded!" | Out-File "$logdir\logfile$LogFile.log" -Append
move-Item -path "$path\$file" -destination $targetdir
}
else
{
Write-Host "Failed! Will retry later." -ForegroundColor Red
"$Timestamp`t$File was not successfully uploaded, will retry later" | Out-File "$logdir\logfile$LogFile.log" -Append
}
}