How to create and verify folders and sub-folders based on a calendar year ?

I wonder How to create and verify folders and sub-folders based on a calendar year ?
For example, year 200
Script will do:
1. Create folder YYYY
1.1. Create subfolder 1 (Month 1 or January)
1.1.1 Create subfolder 1 (Day 1) under the folder 1 (month 1)
1.1.2 Create subfolder 2 (Day 2) under the folder 1 (month 1)
1.1.3 Verify if subfolder for the day exist, if not Create subfolder for the day in this case 3 (Day 3) under the folder 1 (month 1)
1.1.y And so on until the last day of the month 1
1.2 Create subfolder 2 (Month 2 or February)
1.2.1 Create subfolder 1 (Day 1) under the folder 1 (month 2)
1.2.2 Create subfolder 2 (Day 2) under the folder 1 (month 2)
1.2.3 Verify if subfolder for the day exist, if not Create subfolder for the day in this case 3 (Day 3) under the folder 2 (month 2)
1.2.y And so on until the last day of the month 2
1.x. Create subfolder n (until the last month of the year
1.x.y Create subfolder y (Day y) under the folder x (month x).
2. Create folder for the next year and Verify Year
And continue the creation of subfolders about the months and respective days

Do you understand ?

Thanks for your help
namergSystems AdministratorAsked:
Who is Participating?
 
Sajen JoseCommented:
I guess another way of achieving the result would be:

Clear-Host
# Enter the  appropriate year here
$Year = 2018
$MonthList = @("1", "2", "3", "4", "5", "6", "7", "8", "9", "10", "11", "12") 


New-Item -ItemType Directory -Path C:\temp\$Year 

foreach ($monthnum in $MonthList)
{
    $month = (Get-Culture).DateTimeFormat.GetMonthName($monthnum)
    New-Item -ItemType Directory -Path C:\Temp\$Year\$month
    $MonthDays = [datetime]::DaysInMonth($Year, $monthnum)
    for ($i = 1; $i -le $MonthDays; $i++)
    {
        New-Item -ItemType Directory -Path C:\Temp\$Year\$month\$i;
    }

}

Open in new window

0
 
David Johnson, CD, MVPOwnerCommented:
function New-Basepath
{
  <#
    .SYNOPSIS
    Short Description
    .DESCRIPTION
    Detailed Description
    .EXAMPLE
    New-basepath
    explains how to use the command
    can be multiple lines
    .EXAMPLE
    New-basepath
    another example
    can have as many examples as you like
  #>
  param
  (
    [Parameter(Position=0)]
    [string] $basedir = "$env:HOMEDRIVE\Test",
    [Parameter(Position=1)] [int] $month = 1,
    [Parameter(Position=2)][int]$days = 0,
    [Parameter(Position=3)][int]$day = 0,
    [Parameter(Position=4)][int]$year = 200
  )
  
  for ($month -eq 1; $month -le 12; $month++){
    switch($month){
      9 { $days = 30}  # September
      4 { $days = 30}  # April
      6 { $days = 30}  # June
      11 { $days = 30} # November
      2  { 
        if (($year %4) -eq 0) {  #using mod operator
          $days = 29
        }
        else {$days = 28}
      }
      default { $days = 31}
    }
    for ($day = 1; $day -le $days; $day++)
    {
      #     write-output -InputObject $basedir, $year, $days, $day, $month
      $newpath = $basedir + '\' + $year + '\'+$month + '\' + $day
      
      if (!(test-path -Path $newpath)) {
        write-output (('{0} does not exist creating new directory' -f $newpath))
        mkdir -Path $newpath 
        if (!(test-path -Path $newpath)) {
          write-output(('Error creating {0} ' -f $basedir))
          break;
        }
        else {
          write-output (('{0} created' -f $newpath))
        }
      }
    }
  }
}

Open in new window

0
 
namergSystems AdministratorAuthor Commented:
Hmm, will that script covers the 29 vs 28 days of February. Every three years Feb has 29 days.
0
WEBINAR: 10 Easy Ways to Lose a Password

Join us on June 27th at 8 am PDT to learn about the methods that hackers use to lift real, working credentials from even the most security-savvy employees. We'll cover the importance of multi-factor authentication and how these solutions can better protect your business!

 
David Johnson, CD, MVPOwnerCommented:
yes and I edited to add the year  that was missing
0
 
namergSystems AdministratorAuthor Commented:
Can you tell me how would i run the script ?
0
 
namergSystems AdministratorAuthor Commented:
I do not think the user would like to enter parameters at all.
0
 
namergSystems AdministratorAuthor Commented:
What if you create something static but yes beginning in year 200.

I started doing this but i will end up with lot of for and ifs.

#Year2000
$FolderPath = "C:\Scripts\FolderPath\"
$Year2000 = 2000; $DaysMonth1 = 31; $DaysMonth2 = 29; $DaysMonth3 = 31; $DaysMonth4 = 30; $DaysMonth5 = 31; $DaysMonth6 = 30; $DayMonth7 = 31; $DaysMonth8 = 31; $DaysMonth9 = 30; $DaysMonth10 = 31; $DaysMonth11 = 30; $DaysMonth12 = 31
$Year2001 = 2001; $Year2001Month2 = 28
$Year2002 = 2002; $Year2002Month2 = 28
$Year2003 = 2003; $Year2003Month2 = 28
$Year2004 = 2004; $Year2004Month2 = 29
$Year2005 = 2005; $Year2005Month2 = 28
$Year2006 = 2006; $Year2006Month2 = 28
$Year2007 = 2007; $Year2007Month2 = 28
$Year2008 = 2008; $Year2008Month2 = 29
$Year2009 = 2009; $Year2009Month2 = 28
$Year2010 = 2010; $Year2010Month2 = 28
$Year2011 = 2011; $Year2011Month2 = 28
$Year2012 = 2012; $Year2012Month2 = 29
$Year2013 = 2013; $Year2013Month2 = 28
$Year2014 = 2014; $Year2014Month2 = 28
$Year2015 = 2015; $Year2015Month2 = 28
$Year2016 = 2016; $Year2016Month2 = 29
$Year2017 = 2017; $Year2017Month2 = 28
$Year2018 = 2018; $Year2018Month2 = 28


If (test-path  "C:\Scripts\FolderPath\$Year2000") {
Write-host "Folder 2000 does exist"
	If (test-path "C:\Scripts\FolderPath\$Year2000\") {
	
		Write-host "Folder 1 for Month 1 does exist"
	}
}
Else { Write-host "Folder 2000 does NOT exist" }

Open in new window

0
 
David Johnson, CD, MVPOwnerCommented:
it is a function
so you can load it via .\filename.ps1 and then 'new-basepath'  or strip out
function new-basepath 
{

Open in new window

and the ending
}

Open in new window

and save it as a script.ps1 file then you can run
.\script.ps1 -year 2018 -basedir x:\base

get-help .\script.ps1 will show you the command line options available.
0
 
David Johnson, CD, MVPOwnerCommented:
 2  { 
        if (($year %4) -eq 0) {  #using mod operator if year divisible by 4 leaves no remainder then 
          $days = 29
        }
        else {$days = 28}

Open in new window

0
 
namergSystems AdministratorAuthor Commented:
Hmm, i got lost... I understood this part: \script.ps1 -year 2018 -basedir x:\base and what about this:

 { 
        if (($year %4) -eq 0) {  #using mod operator if year divisible by 4 leaves no remainder then 
          $days = 29
        }
        else {$days = 28}

Open in new window

0
 
namergSystems AdministratorAuthor Commented:
I did execute the following .\CreateVerifyCalendar.ps1 -Year 2000 -basedir C:\Scripts\FolderPath but did not do anything
0
 
footechCommented:
Here's an alternative.
$year = Read-Host "Enter year"
$basePath = "C:\temp"
1..((Get-Date "12/31/$year").DayOfYear) | ForEach { ([datetime]"01/01/$year").AddDays($_ - 1).ToString("yyyy\\MM\\dd") } | ForEach `
{
    New-Item -Path (Join-Path $basePath $_) -ItemType Directory | Out-Null
}

Open in new window

0
 
namergSystems AdministratorAuthor Commented:
@footech not quite, see screenshot
Screenshot_1.png
0
 
footechCommented:
What's missing?
There's a folder for the year, under that a folder for each month, and under each month a folder for each day.
folders
0
 
footechCommented:
BTW, I just tested David's code and it did pretty much the same.  One difference is that mine has leading 0's for single-digit days and months, but that's easily changed.
0
 
namergSystems AdministratorAuthor Commented:
@footech hmm about your code very odd it only created 2000\12\31 and not the other subfolders
0
 
namergSystems AdministratorAuthor Commented:
@david when i do the following i do not get any help
PS C:\Scripts> get-help .\CreateVerifyCalendar.ps1
CreateVerifyCalendar.ps1

Open in new window

0
 
footechCommented:
I can't recreate the issue you mentioned.
What version are you running?  Start a new powershell session to test.
0
 
namergSystems AdministratorAuthor Commented:
PS C:\Scripts> $PSVersionTable.PSVersion

Major  Minor  Build  Revision
-----  -----  -----  --------
5      0      10586  117
0
 
namergSystems AdministratorAuthor Commented:
Now, i installed the latest:
PS G:\> $PSVersionTable.PSVersion

Major  Minor  Build  Revision
-----  -----  -----  --------
5      1      14409  1005

And i get the following error:

PS G:\> ((Get-Date "12/31/$year").DayOfYear) | ForEach { ([datetime]"1/1/$year").AddDays($_ - 1).ToString("yyyy\\MM\\dd") } | ForEach {New-Item -Path (Join
-Path $basePath $_) -ItemType Directory | Out-Null}
Get-Date : Cannot bind parameter 'Date'. Cannot convert value "12/31/" to type "System.DateTime". Error: "String was not recognized as a valid DateTime."
At line:1 char:12
+ ((Get-Date "12/31/$year").DayOfYear) | ForEach { ([datetime]"1/1/$yea ...
+            ~~~~~~~~~~~~~
    + CategoryInfo          : InvalidArgument: (:) [Get-Date], ParameterBindingException
    + FullyQualifiedErrorId : CannotConvertArgumentNoMessage,Microsoft.PowerShell.Commands.GetDateCommand

Open in new window

0
 
footechCommented:
Only way to get that is to not run the first line
$year = Read-Host "Enter year"
or enter a blank.
0
 
David Johnson, CD, MVPOwnerCommented:
#requires -Version 2.0
<#
    .SYNOPSIS
    Short Description
    .DESCRIPTION
    Detailed Description
    .EXAMPLE
    New-basepath
    explains how to use the command
    can be multiple lines
    .EXAMPLE
    New-basepath
    another example
    can have as many examples as you like
#>
param
(
  [Parameter(Position = 0)]
  [string] $basedir = "$env:HOMEDRIVE\Test",
  [Parameter(Position = 1)] [int] $month = 1,
  [Parameter(Position = 2)][int]$days = 0,
  [Parameter(Position = 3)][int]$day = 0,
  [Parameter(Position = 4)][int]$year = 200
)
  
for ($month -eq 1; $month -le 12; $month++)
{
  switch($month){
    9 
    {
      $days = 30
    }  # September
    4 
    {
      $days = 30
    }  # April
    6 
    {
      $days = 30
    }  # June
    11 
    {
      $days = 30
    } # November
    2  
    { 
      if (($year %4) -eq 0) 
      {
        #using mod operator
        $days = 29
      }
      else 
      {
        $days = 28
      }
    }
    default 
    {
      $days = 31
    }
  }
  for ($day = 1; $day -le $days; $day++)
  {
    $smonth = $month.tostring('00')
    $sday = $day.tostring('00')
    #     write-output -InputObject $basedir, $year, $days, $day, $month
    $newpath = $basedir + '\' + $year + '\'+$smonth + '\' + $sday
      
    if (!(Test-Path -Path $newpath)) 
    {
      Write-Verbose -Message (('{0} does not exist creating new directory' -f $newpath))
      $null = mkdir -Path $newpath
      if (!(Test-Path -Path $newpath)) 
      {
        Write-Output -InputObject (('Error creating {0} ' -f $basedir))
        break
      }
      else 
      {
        Write-Verbose -Message ('{0} created' -f $newpath)
      }
    }
  }
}
#  }

Open in new window

Added leading 0
Video: https://www.screencast.com/t/FMvT08j8K
0
 
Sajen JoseCommented:
Added the validation check "If Folder exists". You will need to update the value for the $Year and also the path to reflect your choice, currently I have used a random path like C:\Temp, you can use a variable for that as welll

Clear-Host
#Change Value here... 
$Year = 2018
$MonthList = @("1", "2", "3", "4", "5", "6", "7", "8", "9", "10", "11", "12") 

If ((Test-Path C:\temp\$Year) -eq $False)
{
    New-Item -ItemType Directory -Path C:\temp\$Year 

}


foreach ($monthnum in $MonthList)
{
    $month = (Get-Culture).DateTimeFormat.GetMonthName($monthnum)
    
    If((Test-Path C:\Temp\$Year\$month) -eq $False)
    {
        New-Item -ItemType Directory -Path C:\Temp\$Year\$month
    }
    $MonthDays = [datetime]::DaysInMonth($Year, $monthnum)
    for ($i = 1; $i -le $MonthDays; $i++)
    {
        IF((test-path C:\Temp\$Year\$month\$i) -eq $False)
        {
            New-Item -ItemType Directory -Path C:\Temp\$Year\$month\$i;
        }
    }

}

Open in new window

0
 
namergSystems AdministratorAuthor Commented:
@SajeJose almost, almost but what if instead of writing out the name of the months, just the number of the month: 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12 as subfolders ? See attachment
Screenshot_2.png
0
 
namergSystems AdministratorAuthor Commented:
I think i got it.

Clear-Host
#Change Value here... 
$year = Read-Host "Enter year"
#$Year = 2000
$MonthList = @("1", "2", "3", "4", "5", "6", "7", "8", "9", "10", "11", "12") 

If ((Test-Path C:\Scripts\FolderPath\$Year) -eq $False)
{
    New-Item -ItemType Directory -Path C:\Scripts\FolderPath\$Year 

}


foreach ($monthnum in $MonthList)
{
    $monthnum
	$month = (Get-Culture).DateTimeFormat.GetMonthName($monthnum)
    
	If ((Test-Path C:\Scripts\FolderPath\$Year\$monthnum) -eq $False)
    {
		New-Item -ItemType Directory -Path C:\Scripts\FolderPath\$Year\$monthnum
    }
    $MonthDays = [datetime]::DaysInMonth($Year, $monthnum)
    for ($i = 1; $i -le $MonthDays; $i++)
    {
		if ((test-path C:\Scripts\FolderPath\$Year\$monthnum\$i) -eq $False)
        {
			New-Item -ItemType Directory -Path C:\Scripts\FolderPath\$Year\$monthnum\$i;
		}
    }

}

Open in new window

0
 
footechCommented:
Whatever works for you.  There's some pieces in that that aren't really needed, but I won't quibble over them.
I only posted mine to show that it could be done with much fewer lines of code (always better to use datetime methods and properties than trying to build your own logic, in my opinion).  FWIW, I tested on a couple different machines with different OSes and never ran into a problem.  I have to assume the problem's on your end.

If you have no further questions regarding this, please go ahead and close the question.
0
Question has a verified solution.

Are you are experiencing a similar issue? Get a personalized answer when you ask a related question.

Have a better answer? Share it in a comment.

All Courses

From novice to tech pro — start learning today.