else not being executed within foreach - powershell

I am trying to write the following script, which checks a folder for a set of files, if they exist, move them to an "archive" folder. If they don't, write an error message to screen and to a log file.
The files move fine, so the first part of the IF is working correctly, but if there are no files to move, the else should kick in and output the error....but it is not.
variables.ps1:
#----- define parameters -----#
#----- Treat All Errors as Terminating -----#
$ErrorActionPreference = "Stop"
#----- Set count to 0 -----#
$count = 0
#----- get current date ----#
$Now = Get-Date
#----- define amount of days ----#
$Days = "0"
#----- define folder where files are located ----#
$SourceFolder = "C:\HG1\Test\Files"
#----- define folder where files are to be moved to ----#
$DestFolder = "C:\HG1\Test\Files\Archive"
#----- define folder where files are to be moved to ----#
$LogPath = "C:\HG1\archive.log"
#----- define extension ----#
$Extension = "*.log"
#----- define LastWriteTime parameter based on $Days ---#
$LastWrite = $Now.AddDays(-$Days)
#----- get files based on lastwrite filter and specified folder ---#
$Files = Get-Childitem $SourceFolder -Include $Extension -Recurse | Where {$_.LastWriteTime -le "$LastWrite"}
archive_files.ps1
#----- Call variables file variables.ps1 - MUST BE IN SAME LOCATION AS SCRIPT ----#
. ./variables.ps1
foreach ($File in $Files)
{
if ($File -ne $NULL)
{
move-item -path $File.FullName -destination $DestFolder
Add-Content $LogPath -value ("$((Get-Date).ToString('yyyy-MM-dd HH:mm:ss')) `t INFO: Archived File $File")
}
else
{
write-host "ERROR: No files to archive" -ForegroundColor "Red"
Add-Content $LogPath -value ("$((Get-Date).ToString('yyyy-MM-dd HH:mm:ss')) `t ERROR: No files to archive")
}
}
Add-Content $LogPath -value ("$((Get-Date).ToString('yyyy-MM-dd HH:mm:ss')) `t INFO: ***Archiving script completed successfully***")
Any help would be greatly appreciated.

#----- Call variables file variables.ps1 - MUST BE IN SAME LOCATION AS SCRIPT ----#
. ./variables.ps1
if ($File)
{
foreach ($File in $Files)
{
move-item -path $File.FullName -destination $DestFolder
Add-Content $LogPath -value ("$((Get-Date).ToString('yyyy-MM-dd HH:mm:ss')) `t INFO: Archived File $File")
}
}
else
{
write-host "ERROR: No files to archive" -ForegroundColor "Red"
Add-Content $LogPath -value ("$((Get-Date).ToString('yyyy-MM-dd HH:mm:ss')) `t ERROR: No files to archive")
}
Add-Content $LogPath -value ("$((Get-Date).ToString('yyyy-MM-dd HH:mm:ss')) `t INFO: ***Archive script completed successfully***")
here,
Foreach each won't process for $null value
so include foreach if value is not null
if won't enter for $null value so " -ne $null is" not necessary
hopes this works for you,
Regards,
Kvprasoon

You should use the Test-Path cmdlet to check whether the file exist:
foreach ($File in $Files)
{
if (Test-Path $File)
{
move-item -path $File.FullName -destination $DestFolder
Add-Content $LogPath -value ("$((Get-Date).ToString('yyyy-MM-dd HH:mm:ss')) `t INFO: Archived File $File")
}
else
{
write-host "ERROR: No files to archive" -ForegroundColor "Red"
Add-Content $LogPath -value ("$((Get-Date).ToString('yyyy-MM-dd HH:mm:ss')) `t ERROR: No files to archive")
}
}
Add-Content $LogPath -value ("$((Get-Date).ToString('yyyy-MM-dd HH:mm:ss')) `t INFO: ***Archiving script completed successfully***")

You've got that logic backwards there.
Each $File in $Files will always be something, but the $Files collection itself may be empty:
if(-not $Files)
{
foreach($File in $Files)
{
Move-Item -Path $File.FullName -Destination $DestFolder
Add-Content $LogPath -Value ("$((Get-Date).ToString('yyyy-MM-dd HH:mm:ss')) `t INFO: Archived File $File")
}
}
else
{
Write-Host "ERROR: No files to archive" -ForegroundColor "Red"
Add-Content $LogPath -Value ("$((Get-Date).ToString('yyyy-MM-dd HH:mm:ss')) `t ERROR: No files to archive")
}
Add-Content $LogPath -value ("$((Get-Date).ToString('yyyy-MM-dd HH:mm:ss')) `t INFO: ***Archiving script completed successfully***")

Related

Archive files from a folder which are older than one week to a sub folder using powershell

I have tried below powershell script to move files older than 7 days from Newfolder to Archive_folder. The script is moving the entire path to the Archive_folder (means its creating folders \Users\529817\New folder in to Archive_folder and then copying files and not zipping the folder) , I need help in copying only files from NewFolder to Archive_folder and zip that folder.
$ArchiveYear = "2018"
$ArchiveMonth = "10"
$ArchiveDay = "10"
$SourcePath = "C:\Users\529817\New folder"
$TargetPath = "C:\Users\529817\New folder\Archive_folder"
$YourDirToCompress = "C:\Users\529817\New folder"
$ZipFileResult = "C:\Users\529817\New folder\Archive_folder\$ArchiveDay$ArchiveMonth.zip"
Get-ChildItem $YourDirToCompress -Directory |
#where { $_.Name -notin $DirToExclude} |
Compress-Archive -DestinationPath $ZipFileResult -Update
$Days = "7"
$LogPath = "C:Users\529817\Temp"
$Date = Get-Date -format yyyy-MM-dd_HH-mm
$TargetFolder = "$TargetPath\$Date"
$LogFile = "$LogPath\ArchiveLog-$date.txt"
$TargetZipFile = "$TargetPath\$Date.zip"
$Activity = "Move files older than $Days days from $SourcePath to $TargetFolder"
Write-Verbose $Activity
$OldFiles = Get-Childitem -Path $SourcePath -recurse | Where-Object {$_.LastWriteTime -lt (get-date).AddDays( - $days)}
$Total = $Oldfiles.Count
$Current = 0
$OldFiles | ForEach {
$Current ++
$Filename = $_.fullname
Write-Progress -Activity $Activity -Status $FileName -PercentComplete ($Current / $Total * 100)
$Split = $FileName -split '\\'
$DestFile = $split[1..($split.Length - 1)] -join '\'
$DestFile = "$TargetFolder\$DestFile"
Try {
$null = New-Item -Path $DestFile -Type File -Force
$Null = Move-Item -Path $FileName -Destination $DestFile -Force -ErrorAction:SilentlyContinue
"Successfully moved $filename to $targetfolder" | add-content $LogFile
}
Catch {
$Err = $_.Exception.Message
Write-Error $Err
"Error moving $filename`: $Err " | add-content $LogFile
}
}
You have two problems here:
Your zip file isn't going where you want it to go
Instead, all of the items which should be in the zip are going where the zip should go.
Let's figure out why this is happening so you can do what you need to get it working.
Problem 1
You have line 10 which looks like this:
Compress-Archive -DestinationPath $ZipFileResult -Update
This creates the Zip file but you don't actually do anything with this file, as in we don't see this $ZipFileResult used again in the code. This is why your zip file isn't showing up where you want it to be.
Problem 2
The end of this script has this big block where you are expressly copying the files to the directory,right where you don't want them.
Try {
$null = New-Item -Path $DestFile -Type File -Force
$Null = Move-Item -Path $FileName -Destination $DestFile -Force -ErrorAction:SilentlyContinue
"Successfully moved $filename to $targetfolder" | add-content $LogFile
}
If you only want to move the Zip file, then you can shorten this whole script. Delete everything from line 19 and on down, which begins with this line.
$OldFiles = Get-Childitem -Path $SourcePath -recurse | Where-Object {$_.LastWriteTime -lt (get-date).AddDays( - $days)}
And instead, add a Move-Item command to copy that $ZipFileResult file over to whichever directory you want it to go.
Finally, there are a number of lines which don't do anythign and can be deleted, like this line $TargetZipFile = "$TargetPath\$Date.zip"

How do I show progress of copying files older than 1 day from one folder to other another?

We need to know in code what files were copied and some files were old and were not copied.
$date = (get-date).AddDays(-1)
get-childitem -File c:\t\*.*,c:\f\*.*,c:\u\*.*,c:\s\*.* | where-object {$_.LastWriteTime -gt $date} |
Copy-Item -Destination c:\t\1 ```
If you're on PowerShell 4.0 or newer, you could use the .Where({}) extension method in "Split" mode to split new and old files into two groups:
$new,$old = #(Get-ChildItem -File C:\t\*.*).Where({$_.LastWriteTime -gt $date}, 'Split')
# Write file names to log files
$new.Name > newfiles.txt
$old.Name > oldfiles.txt
$new | Copy-Item -Destination C:\t\1\
If by 'showing progress' you mean writing some info to the console, then this could be what you want.
$date = (Get-Date).AddDays(-1)
$dest = 'C:\t\1'
# if the destination folder does not exist, create it first
if (!(Test-Path $dest -PathType Container)) {
New-Item -Path $dest -ItemType Directory | Out-Null
}
Get-ChildItem -Path 'C:\t','C:\f','C:\u','C:\s' -File | ForEach-Object {
if ($_.LastWriteTime -gt $date) {
Write-Host "Copying file '$($_.FullName)'" -ForegroundColor Green
$_ | Copy-Item -Destination $dest
}
else {
Write-Host "File '$($_.FullName)' is too old.. Skipped" -ForegroundColor Yellow
}
}

Windows Profile Backup Script - Access Denied for Desktop Files

I am using a script I modified slightly to backup user library files. For some reason it can backup all libraries but fails to backup any of the Desktop files.
I've tried running this as various users and on different machines but with the same result.
This is in the latest Powershell version on Windows 10. Perhaps the code has changed since Windows 7? Thanks in advance for any help.
Set-StrictMode -Off
#create directories for backup if needed
$TARGETDIR1 = "c:\temp"
if(!(Test-Path -Path $TARGETDIR1 )){
New-Item -ItemType directory -Path $TARGETDIR1
}
$TARGETDIR2 = "c:\temp\backup"
if(!(Test-Path -Path $TARGETDIR2 )){
New-Item -ItemType directory -Path $TARGETDIR2
}
$TARGETDIR3 = "c:\temp\backup\Download"
if(!(Test-Path -Path $TARGETDIR3 )){
New-Item -ItemType directory -Path $TARGETDIR3
}
$TARGETDIR4 = "c:\temp\backup\Staging"
if(!(Test-Path -Path $TARGETDIR4 )){
New-Item -ItemType directory -Path $TARGETDIR4
}
#Variables, only Change here
$Destination="c:\temp\backup" #Copy the Files to this Location
$Destination="C:\temp\backup\Download"
$Staging="C:\temp\backup\Staging"
$ClearStaging=$true # When $true, Staging Dir will be cleared
$Versions="5" #How many of the last Backups you want to keep
$BackupDirs="$env:USERPROFILE\Desktop", "$env:USERPROFILE\Documents", "$env:USERPROFILE\Downloads", "$env:USERPROFILE\Favorites", "$env:USERPROFILE\Pictures", "$env:USERPROFILE\Videos", "$env:USERPROFILE\OneDrive", "$env:USERPROFILE\Links"#What Folders you want to backup
#commented out for now --tom
$ExcludeDirs="C:\Users\seimi\OneDrive - Seidl Michael\0-Temp\Dir1","C:\Users\seimi\OneDrive - Seidl Michael\0-Temp\Dir2" #This list of Directories will not be copied
$LogName="Log.txt" #Log Name
$LoggingLevel="3" #LoggingLevel only for Output in Powershell Window, 1=smart, 3=Heavy
$Zip=$false #Zip the Backup Destination
$Use7ZIP=$false #Make sure it is installed
$RemoveBackupDestination=$false #Remove copied files after Zip, only if $Zip is true
$UseStaging=$true #only if you use ZIP, than we copy file to Staging, zip it and copy the ZIP to destination, like Staging, and to save NetworkBandwith
#Send Mail Settings
# $SendEmail = $false # = $true if you want to enable send report to e-mail (SMTP send)
# $EmailTo = 'test#domain.com' #user#domain.something (for multiple users use "User01 <user01#example.com>" ,"User02 <user02#example.com>" )
# $EmailFrom = 'from#domain.com' #matthew#domain
# $EmailSMTP = 'smtp.domain.com' #smtp server adress, DNS hostname.
#STOP-no changes from here
#STOP-no changes from here
#Settings - do not change anything from here
$ExcludeString=""
#[string[]]$excludedArray = $ExcludeDirs -split ","
foreach ($Entry in $ExcludeDirs)
{
$Temp="^"+$Entry.Replace("\","\\")
$ExcludeString+=$Temp+"|"
}
$ExcludeString=$ExcludeString.Substring(0,$ExcludeString.Length-1)
#$ExcludeString
[RegEx]$exclude = $ExcludeString
if ($UseStaging -and $Zip)
{
#Logging "INFO" "Use Temp Backup Dir"
$Backupdir=$Staging +"\Backup-"+ (Get-Date -format yyyy-MM-dd)+"-"+(Get-Random -Maximum 100000)+"\"
}
else
{
#Logging "INFO" "Use orig Backup Dir"
$Backupdir=$Destination +"\Backup-"+ (Get-Date -format yyyy-MM-dd)+"-"+(Get-Random -Maximum 100000)+"\"
}
#$BackupdirTemp=$Temp +"\Backup-"+ (Get-Date -format yyyy-MM-dd)+"-"+(Get-Random -Maximum 100000)+"\"
$Log=$Backupdir+$LogName
$Log
$Items=0
$Count=0
$ErrorCount=0
$StartDate=Get-Date #-format dd.MM.yyyy-HH:mm:ss
#FUNCTION
#Logging
Function Logging ($State, $Message) {
$Datum=Get-Date -format dd.MM.yyyy-HH:mm:ss
if (!(Test-Path -Path $Log)) {
New-Item -Path $Log -ItemType File | Out-Null
}
$Text="$Datum - $State"+":"+" $Message"
if ($LoggingLevel -eq "1" -and $Message -notmatch "was copied") {Write-Host $Text}
elseif ($LoggingLevel -eq "3") {Write-Host $Text}
add-Content -Path $Log -Value $Text
}
#Create Backupdir
Function Create-Backupdir {
New-Item -Path $Backupdir -ItemType Directory | Out-Null
sleep -Seconds 5
Logging "INFO" "Create Backupdir $Backupdir"
}
#Delete Backupdir
Function Delete-Backupdir {
$Folder=Get-ChildItem $Destination | where {$_.Attributes -eq "Directory"} | Sort-Object -Property CreationTime -Descending:$false | Select-Object -First 1
Logging "INFO" "Remove Dir: $Folder"
$Folder.FullName | Remove-Item -Recurse -Force
}
#Delete Zip
Function Delete-Zip {
$Zip=Get-ChildItem $Destination | where {$_.Attributes -eq "Archive" -and $_.Extension -eq ".zip"} | Sort-Object -Property CreationTime -Descending:$false | Select-Object -First 1
Logging "INFO" "Remove Zip: $Zip"
$Zip.FullName | Remove-Item -Recurse -Force
}
#Check if Backupdirs and Destination is available
function Check-Dir {
Logging "INFO" "Check if BackupDir and Destination exists"
if (!(Test-Path $BackupDirs)) {
return $false
Logging "Error" "$BackupDirs does not exist"
}
if (!(Test-Path $Destination)) {
return $false
Logging "Error" "$Destination does not exist"
}
}
#Save all the Files
# note - if the folders are empty that are being copied you will see errors
# this shouldn't affect the backup --Tom
Function Make-Backup {
Logging "INFO" "Started the Backup"
$Files=#()
$SumMB=0
$SumItems=0
$SumCount=0
$colItems=0
Logging "INFO" "Count all files and create the Top Level Directories"
}
foreach ($Backup in $BackupDirs) {
$colItems = (Get-ChildItem $Backup -Recurse -File | Where-Object {$_.mode -notmatch "h"} | Measure-Object -property length -sum)
$Items=0
$FilesCount += Get-ChildItem $Backup -Recurse -File | Where-Object {$_.mode -notmatch "h"}
Copy-Item -Path $Backup -Destination $Backupdir -Force -ErrorAction SilentlyContinue
$SumMB+=$colItems.Sum.ToString()
$SumItems+=$colItems.Count
$TotalMB="{0:N2}" -f ($SumMB / 1MB) + " MB of Files"
Logging "INFO" "There are $SumItems Files with $TotalMB to copy"
foreach ($Backup in $BackupDirs) {
$Index=$Backup.LastIndexOf("\")
$SplitBackup=$Backup.substring(0,$Index)
$Files = Get-ChildItem $Backup -Recurse | select * | Where-Object {$_.mode -notmatch "h" -and $_.fullname -notmatch $exclude} | select fullname #$_.mode -notmatch "h" -and
foreach ($File in $Files) {
$restpath = $file.fullname.replace($SplitBackup,"")
try {
Copy-Item $file.fullname $($Backupdir+$restpath) -Force -ErrorAction SilentlyContinue |Out-Null
Logging "INFO" "$file was copied"
}
catch {
$ErrorCount++
Logging "ERROR" "$file returned an error an was not copied"
}
$Items += (Get-item $file.fullname).Length
$status = "Copy file {0} of {1} and copied {3} MB of {4} MB: {2}" -f $count,$SumItems,$file.Name,("{0:N2}" -f ($Items / 1MB)).ToString(),("{0:N2}" -f ($SumMB / 1MB)).ToString()
$Index=[array]::IndexOf($BackupDirs,$Backup)+1
$Text="Copy data Location {0} of {1}" -f $Index ,$BackupDirs.Count
Write-Progress -Activity $Text $status -PercentComplete ($Items / $SumMB*100)
if ($File.Attributes -ne "Directory") {$count++}
}
}
$SumCount+=$Count
$SumTotalMB="{0:N2}" -f ($Items / 1MB) + " MB of Files"
Logging "INFO" "----------------------"
Logging "INFO" "Copied $SumCount files with $SumTotalMB"
Logging "INFO" "$ErrorCount Files could not be copied"
# Send e-mail with reports as attachments
if ($SendEmail -eq $true) {
$EmailSubject = "Backup Email $(get-date -format MM.yyyy)"
$EmailBody = "Backup Script $(get-date -format MM.yyyy) (last Month).`nYours sincerely `Matthew - SYSTEM ADMINISTRATOR"
Logging "INFO" "Sending e-mail to $EmailTo from $EmailFrom (SMTPServer = $EmailSMTP) "
### the attachment is $log
Send-MailMessage -To $EmailTo -From $EmailFrom -Subject $EmailSubject -Body $EmailBody -SmtpServer $EmailSMTP -attachment $Log
}
}
#create Backup Dir
Create-Backupdir
Logging "INFO" "----------------------"
Logging "INFO" "Start the Script"
#Check if Backupdir needs to be cleaned and create Backupdir
$Count=(Get-ChildItem $Destination | where {$_.Attributes -eq "Directory"}).count
Logging "INFO" "Check if there are more than $Versions Directories in the Backupdir"
if ($count -gt $Versions)
{
Delete-Backupdir
}
$CountZip=(Get-ChildItem $Destination | where {$_.Attributes -eq "Archive" -and $_.Extension -eq ".zip"}).count
Logging "INFO" "Check if there are more than $Versions Zip in the Backupdir"
if ($CountZip -gt $Versions) {
Delete-Zip
}
#Check if all Dir are existing and do the Backup
$CheckDir=Check-Dir
if ($CheckDir -eq $false) {
Logging "ERROR" "One of the Directory are not available, Script has stopped"
} else {
Make-Backup
$Enddate=Get-Date #-format dd.MM.yyyy-HH:mm:ss
$span = $EndDate - $StartDate
$Minutes=$span.Minutes
$Seconds=$Span.Seconds
Logging "INFO" "Backupduration $Minutes Minutes and $Seconds Seconds"
Logging "INFO" "----------------------"
Logging "INFO" "----------------------"
if ($Zip)
{
Logging "INFO" "Compress the Backup Destination"
if ($Use7ZIP)
{
Logging "INFO" "Use 7ZIP"
if (-not (test-path "$env:ProgramFiles\7-Zip\7z.exe")) {Logging "WARNING" "7Zip not found"}
set-alias sz "$env:ProgramFiles\7-Zip\7z.exe"
#sz a -t7z "$directory\$zipfile" "$directory\$name"
if ($UseStaging -and $Zip)
{
$Zip=$Staging+("\"+$Backupdir.Replace($Staging,'').Replace('\','')+".zip")
sz a -t7z $Zip $Backupdir
Logging "INFO" "Move Zip to Destination"
Move-Item -Path $Zip -Destination $Destination
if ($ClearStaging)
{
Logging "INFO" "Clear Staging"
Get-ChildItem -Path $Staging -Recurse -Force | remove-item -Confirm:$false -Recurse
}
}
else
{
sz a -t7z ($Destination+("\"+$Backupdir.Replace($Destination,'').Replace('\','')+".zip")) $Backupdir
}
}
else
{
Logging "INFO" "Use Powershell Compress-Archive"
Compress-Archive -Path $Backupdir -DestinationPath ($Destination+("\"+$Backupdir.Replace($Destination,'').Replace('\','')+".zip")) -CompressionLevel Optimal -Force
}
If ($RemoveBackupDestination)
{
Logging "INFO" "Backupduration $Minutes Minutes and $Seconds Seconds"
#Remove-Item -Path $BackupDir -Force -Recurse
get-childitem -Path $BackupDir -recurse -Force | remove-item -Confirm:$false -Recurse
get-item -Path $BackupDir | remove-item -Confirm:$false -Recurse
}
}
}
Write-Host "Press any key to close ..."
$x = $host.UI.RawUI.ReadKey("NoEcho,IncludeKeyDown")
The output of the log file shows the failure here:
03.05.2019-15:01:04 - ERROR: #{FullName=C:\Users\REDACTED\Desktop\Microsoft Edge.lnk} returned an error an was not copied
03.05.2019-15:01:04 - ERROR: #{FullName=C:\Users\REDACTED\Desktop\Microsoft Teams.lnk} returned an error an was not copied
03.05.2019-15:01:04 - ERROR: #{FullName=C:\Users\REDACTED\Desktop\PRMS Multi-Session.lnk} returned an error an was not copied
03.05.2019-15:01:04 - ERROR: #{FullName=C:\Users\REDACTED\Desktop\PRMS.lnk} returned an error an was not copied
Here is the output Powershell shows
03.05.2019-15:36:07 - ERROR: #{FullName=C:\Users\REDACTED\Desktop\desktop.ini} returned an error an was not copied
03.05.2019-15:36:07 - ERROR: #{FullName=C:\Users\REDACTED\Desktop\REDACTED Logos & Documents.lnk} returned an error an was not copied
03.05.2019-15:36:07 - ERROR: #{FullName=C:\Users\REDACTED\Desktop\REDACTED VPN - Shortcut.lnk} returned an error an was not copied
03.05.2019-15:36:07 - ERROR: #{FullName=C:\Users\REDACTED\Desktop\REDACTED_DigitalNET (J) - Shortcut.lnk} returned an error an was not copied
03.05.2019-15:36:07 - ERROR: #{FullName=C:\Users\REDACTED\Desktop\REDACTED_Sales (S) - Shortcut.lnk} returned an error an was not copied
03.05.2019-15:36:07 - ERROR: #{FullName=C:\Users\REDACTED\Desktop\Slack.lnk} returned an error an was not copied
03.05.2019-15:36:07 - ERROR: #{FullName=C:\Users\REDACTED\Desktop\REDACTED (U) - Shortcut.lnk} returned an error an was not copied
03.05.2019-15:36:07 - ERROR: #{FullName=C:\Users\REDACTED\Desktop\Visual Studio 2019.lnk} returned an error an was not copied
03.05.2019-15:36:07 - INFO: #{FullName=C:\Users\REDACTED\Documents\ConnectWiseControl} was copied
03.05.2019-15:36:07 - INFO: #{FullName=C:\Users\REDACTED\Documents\OneNote Notebooks} was copied
03.05.2019-15:36:07 - INFO: #{FullName=C:\Users\REDACTED\Documents\Visual Studio 2019} was copied

Powershell: Move files to folder based on Date Created

I'm not a coder but I've still attempted tweaking PS scripts found here and still can't get the behavior I desire. The tough part for me has been the 2 digit Day requirement (dd). After several noob attempts I would like some help.
I have a folder that contains hundreds of JPG's. I manually sort these JPG's into folders based on the date taken. Folder name examples are 2015.02.04, 2016.10.31, 2016.12.01.
1) I would like a script to scan my JPG folder.
2) For each file, scan the date
3) If the file was created June 1st, 2016 then it will be moved to .\2016.06.01
Help a brother out?
$Filepath = ""
$file = ""
$date = ""
$month = ""
$year = ""
$MonthPath = ""
$FilePath = Read-Host "Place the directory which contains the files."
Write-Warning "Note: This action can take several minutes, depending on the amount of files in $FilePath."
get-childitem $FilePath | % {
$file = $_.FullName
$date = Get-Date ($_.LastWriteTime)
$month = $date.month
$year = $date.year
$day = $date.day
$MonthPath = "$FilePath\$year.$month.$day"
Write-Verbose "month = $month"
Write-Verbose "Date = $date"
Write-Verbose "year = $year"
Write-Verbose "FilePath = $FilePath"
Write-Verbose "Filename = $file"
Write-Verbose "MonthPath = $MonthPath"
if(!(Test-Path -Path "$MonthPath" )){
Write-Verbose "Creating log location $MonthPath."
#Write-Host -backgroundcolor green -ForegroundColor black "Creating log location $MonthPath."
Write-Verbose "MonthPath inside path test = $MonthPath"
New-Item -ItemType directory -Path $MonthPath | Out-null
}
ELSE {
#Write-Host -backgroundcolor green -ForegroundColor black "Log location exists already exist $MonthPath"
Write-Verbose "Log location exists already exist $MonthPath"
}
move-item "$file" "$MonthPath" | Out-null
}
Write-Warning "All files are sorted now based upon year and month."
[DateTime]$start_time="2016-6-1 00:00:00"
[DateTime]$end_time="2016-6-1 23:59:59"
$des_folder = "C:\test\2016.06.1"
Get-ChildItem c:\test\*.jpg -Recurse | foreach {if($_.lastwritetime -ge $start_time -and $_.lastwritetime -le $end_time) { move-item $_.fullname $des_folder }}
Please ensure there is no name conflict .
You may change"c:\test" in "c:\test*.jpg" to the path you want to scan .
Also the value of variable "$des_folder" to the destination folder you want to store the matched pictures .
EDIT:
Get-ChildItem c:\test\test2\*.jpg -Recurse | foreach {
$x = $_.LastWriteTime.ToShortDateString()
$new_folder_name = Get-Date $x -Format yyyy.MM.dd
$des_path = "c:\test\test2\$new_folder_name"
if (test-path $des_path){
move-item $_.fullname $des_path
} else {
new-item -ItemType directory -Path $des_path
move-item $_.fullname $des_path
}
}
I ended up creating a script that does exactly what you're asking for here. You can find it in GitHub here, which will have the latest version of the code.
Here is the current implementation, edited for conciseness, removed unnecessary features, and tailored to the question's needs:
[string] $SourceDirectoryPath = 'C:\FilesToMove'
[string] $TargetDirectoryPath = 'C:\SortedFiles'
[System.Collections.ArrayList] $filesToMove = Get-ChildItem -Path $SourceDirectoryPath -File -Force -Recurse
$filesToMove | ForEach-Object {
[System.IO.FileInfo] $file = $_
[DateTime] $fileDate = $file.LastWriteTime
[string] $dateDirectoryName = $fileDate.ToString('yyyy.MM.dd')
[string] $dateDirectoryPath = Join-Path -Path $TargetDirectoryPath -ChildPath $dateDirectoryName
if (!(Test-Path -Path $dateDirectoryPath -PathType Container))
{
Write-Verbose "Creating directory '$dateDirectoryPath'."
New-Item -Path $dateDirectoryPath-ItemType Directory -Force > $null
}
[string] $filePath = $file.FullName
Write-Information "Moving file '$filePath' into directory '$dateDirectoryPath'."
Move-Item -Path $filePath -Destination $dateDirectoryPath
}
Note that it copies the file paths into an array before iterating over them. This is important for the cases where you are copying files to subdirectories of their current directory, otherwise Get-ChildItem could scan files twice, iterating over files that it just moved.
Expanded more to cover off duplicates
$jpg_files = Get-ChildItem "F:\*.jpg" -Recurse
foreach ($jpg in $jpg_files){
$x = $jpg.LastWriteTime.ToShortDateString()
$new_folder = Get-Date $x -Format yyyy-MM-dd
$des_path = "F:\Photos\$($new_folder)"
if (Test-Path $des_path){
if (Test-Path "$($des_path)\$($jpg.Name)"){
$index = 1
do {
$new_name = $des_path + "\" + $jpg.BaseName + " ($($index))" + $jpg.Extension
$index++
} While(Test-Path $new_name)
move-item $jpg.fullname -destination $new_name
}else {
move-item $jpg.fullname $des_path
}
}
else {
new-item -ItemType directory -Path $des_path
move-item $jpg.fullname $des_path
}
I would like to propose this variant based on last response for duplicates showing that multiple files can be selected and also that removing the absolute paths works and it will move the files that are bellow of your current prompt no mathers where the file is. Also add a missing }. Thanks to all that contributes to this thread, this helps a lot to organize the pictures and video!
$files = Get-ChildItem "*.jpg","*.mp4" -Recurse
foreach ($file in $files) {
$x = $file.LastWriteTime.ToShortDateString()
$new_folder = Get-Date $x -Format yyyy-MM
$des_path = "$($new_folder)"
if (Test-Path $des_path) {
if (Test-Path "$($des_path)\$($file.Name)") {
$index = 1
do {
$new_name = $des_path + "\" + $file.BaseName + " ($($index))" + $file.Extension
$index++
} While(Test-Path $new_name)
move-item $file.fullname -destination $new_name
}else {
move-item $file.fullname $des_path
}
}
else {
new-item -ItemType directory -Path $des_path
move-item $file.fullname $des_path
}
}

PowerShell Move-Item $filename

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