Powershell script not creating a folder using mkdir function - powershell

I'm looking to create daily folders using a Powershell script, and while the first 2 folders are being created no problem, the third folder on my list isn't being created. Below is my code, and it's the Raw Data folder that's not being created for some reason - any suggestions as to why this may be happening?
$months = Get-Date -UFormat %b
$monthl = Get-Date -UFormat %B
$year = Get-Date -UFormat %Y
$timestamp = Get-Date -UFormat "%d%m%Y"
$folderstamp = Get-Date -UFormat "%d-%m-%Y"
mkdir "X:\Client Services & Fulfilment\Fulfilment\CMS\$year\$monthl $year\Investec_AML\$folderstamp"
mkdir "X:\Client Services & Fulfilment\Fulfilment\CMS\$year\$monthl $year\Investec_AML\$folderstamp\Final Output"
mkdir "X:\Client Services & Fulfilment\Fulfilment\CMS\$year\$monthl $year\Investec_AML\$folderstamp\Raw Data"
If I write out that line of code on Powershell itself, it returns a LastWriteTime date of 01/01/1601?! See screenshot link below. The mode seems to show all possible modes available?
powershell screenshot

From your screenshot, I can see the Raw Data folder indeed exists. Under Mode you can see its attributes:
d - Directory
a - Archive
r - Read-only
h - Hidden
s - System
l - Reparse point, symlink, etc.
Maybe you should investigate that folder (or link) some more to find out why it is there and if it is a symlink, where it points to.
Anyway, here's your code in more PowerShell style:
$now = Get-Date
$months = $now.ToString("MMM")
$monthl = $now.ToString("MMMM")
$year = $now.Year
$timestamp = $now.ToString("ddMMyyyy")
$folderstamp = $now.ToString("dd-MM-yyyy")
$folderName = "X:\Client Services & Fulfilment\Fulfilment\CMS\$year\$monthl $year\Investec_AML\$folderstamp"
try {
New-Item -ItemType Directory -Path $folderName -ErrorAction Stop | Out-Null
New-Item -ItemType Directory -Path (Join-Path -Path $folderName -ChildPath 'Final Output') -ErrorAction Stop | Out-Null
New-Item -ItemType Directory -Path (Join-Path -Path $folderName -ChildPath 'Raw Data') -ErrorAction Stop | Out-Null
}
catch {
Write-Error $_.Exception.Message
}
Hope that helps

For whatever the reason (the word Raw perhaps?), replacing the space in the new directory name with an underscore has worked i.e. 'Raw_Data' instead of 'Raw Data', so I will roll this out for other daily jobs we process that use a similar folder structure.
Thanks to Theo for the tidier code!
$now = Get-Date
$months = $now.ToString("MMM")
$monthl = $now.ToString("MMMM")
$year = $now.Year
$timestamp = $now.ToString("ddMMyyyy")
$folderstamp = $now.ToString("dd-MM-yyyy")
$folderName = "X:\Client Services & Fulfilment\Fulfilment\CMS\$year\$monthl $year\Investec_AML\$folderstamp"
try {
New-Item -ItemType Directory -Path $folderName -ErrorAction Stop | Out-Null
New-Item -ItemType Directory -Path (Join-Path -Path $folderName -ChildPath 'Final_Output') -ErrorAction Stop | Out-Null
New-Item -ItemType Directory -Path (Join-Path -Path $folderName -ChildPath 'Raw_Data') -ErrorAction Stop | Out-Null
}
catch {
Write-Error $_.Exception.Message
}

Related

Moving files older than X days not working in Powershell

I have the following code:
$dt = Get-Date -format "MM-dd-yyyy"
$logFolder = '\\192.168.20.151\user_backups\Veeam_Logs'
$source = "$logFolder\*.log"; $destination = "$logFolder\Backup Logs [$dt]"
New-Item -ItemType Directory -Path $destination -Force
Move-Item ($source | Where LastWriteTime -gt (Get-Date).AddDays(-7)) $destination -Force
I'm trying to move *.log files in its current directory (so not folders & not recursive) to its sub-folder but only those log files that are older than 7 days. For some reason the above isn't working as it's still copying files that are 20 days old. There's no error.
Also I don't want it to give me any errors if there are no *.log files to copy (or at least when there's no match). -ErrorAction SilentlyContinue didn't work for some reason.
Your help is appreciated.
To perform a condition against LastWriteTime attribute, you need to first return a FileInfoObject. A path string passed into Move-Item -Path won't have the attribute. You can do something like the following:
$dt = Get-Date -format "MM-dd-yyyy"
$logFolder = '\\192.168.20.151\user_backups\Veeam_Logs'
$destination = "$logFolder\Backup Logs [$dt]"
$source = Get-ChildItem -Path "$logFolder\*.log" | Where LastWriteTime -gt (Get-Date).AddDays(-7)
New-Item -ItemType Directory -Path $destination -Force
Move-Item -LiteralPath $source -Destination $destination -Force
$source here performs all the conditional logic. It is unclear if you want files newer or older than a certain date. If you want files that are newer than $date, you will want to use LastWriteTime -gt $date. If you want files older than $date, you will want to use LastWriteTime -lt $date.
You can have -Path value perform the logic, but you must pass in an expression.
$dt = Get-Date -format "MM-dd-yyyy"
$logFolder = '\\192.168.20.151\user_backups\Veeam_Logs'
$destination = "$logFolder\Backup Logs [$dt]"
$source = Get-ChildItem -Path "$logFolder\*.log"
New-Item -ItemType Directory -Path $destination -Force
Move-Item -LiteralPath ($source | Where LastWriteTime -gt (Get-Date).AddDays(-7)) -Destination $destination -Force

Path is denied, not able to run ps1 script

Trying to run the following, but getting a message path is denied
I am new to powershell
Set-Location -Path "C:\work\test
$newFILEStest=(1..100)
foreach($f in $newFILEStest)
{
$newFiletest1="business" +$f + ".txt"
new-item $newfiletest1 -path $source_businesspath
}
$source_businesspath = "C:\work\test\$(Get-Date -Format "yyyy-MM-dd")\business
Goal is: loop generate files such as business.txt inside of the subfolder: business.
Be able to run the ps1 file outside of PS command line
I've fixed the many quoting and logic problems here.
$source_businesspath = "work\test\$(Get-Date -Format 'yyyy-MM-dd')\business"
mkdir $source_businesspath
$newFILEStest=(1..10)
foreach($f in $newFILEStest)
{
$newFiletest1="business" +$f + ".txt"
new-item -name $newfiletest1 -path $source_businesspath
}
You need to make sure that your destination path exists before you create items in it. A simple Test-Path will be able to validate that the directory exists.
Obviously, you also need to have permission to create the directory and files.
$source_businesspath = "C:\Work\Test\$(Get-Date -Format 'yyyy-MM-dd')\business"
if (-not (Test-Path -Path $source_businesspath)) {
New-Item -Path $source_businesspath -ItemType Directory -Force
}
$newFILEStest = (1..10)
foreach ($f in $newFILEStest) {
$newFiletest1 = "business" + $f + ".txt"
New-Item -Path $source_businesspath -Name $newfiletest1
}

Copy-Item is copying unexpected folder

I'm struggling to understand how PowerShell handles recursion and Copy-Item command.
$date=Get-Date -Format yyyyMMdd
$oldfolder="c:\certs\old\$date"
New-PSDrive -Name "B" -PSProvider FileSystem -Root "\\(server)\adconfig"
$lastwrite = (get-item b:\lcerts\domain\wc\cert.pfx).LastWriteTime
$timespan = new-timespan -days 1 -hours 1
Write-Host "testing variables..."
Write-Host " date = $date" `n "folder path to create = $oldfolder" `n
"timespan = $timespan"
if (((get-date) - $lastwrite) -gt $timespan) {
#older
Write-Host "nothing to update."
}
else {
#newer
Write-Host "newer certs available, moving certs to $oldfolder"
copy-item -path "c:\certs\wc" -recurse -destination $oldfolder
copy-item b:\lcerts\domain\wc\ c:\certs\ -recurse -force
}
Existing files exist at c:\certs\wc\cert.pfx
I have the "test" comparing the time between the cert.pfx in the b:\lcerts\domain\wc\ folder and the current time . If the cert has been modified in the past 1 day and 1 hour, then the script should continue:
Copy cert.pfx from c:\certs\wc\ to c:\certs\old\$date\cert.pfx
Copy cert.pfx from b:\lcerts\domain\wc to c:\certs\wc\cert.pfx
I obviously don't understand PowerShell nomenclature for this because the first time I run this script, it works fine. The second time it creates another folder inside c:\certs\wc\$date\wc\cert.pfx.
How do I get it to fail with "c:\certs\wc\$date\cert.pfx already exists?"
I don't want to restrict this to just the cert.pfx file by specifying the actual file name, I want all files in the folder as eventually there will be more than one file.
The behavior of Copy-Item when a directory is specified in the -Path parameter depends on whether the directory specified in the -Destination parameter exists.
Copy-Item -Path "c:\certs\wc" -Recurse -Destination "c:\certs\old\$date"
If the c:\certs\old\$date directory does not exist, then the wc directory is copied and named c:\certs\old\$date.
If the c:\certs\old\$date directory exists, the wc directory is copied under the c:\certs\old\$date directory. Therefore, it becomes c:\certs\old\$date\wc.
So you are sure to check in advance if the directory exists.
if(Test-Path $oldfolder) { throw "'$oldfolder' is already exists." }
Copy-Item -Path "c:\certs\wc" -Destination $oldfolder -Recurse
You are not testing if the destination folder exists. Seeing you are creating its name using a current date, it is more than likely this folder does not yet exist, so you need to create it first.
Also, There should be no need to use the New-PSDrive cmdlet, because Copy-Item is perfectly able to use UNC paths.
Something like this perhaps:
$server = '<NAME OF THE SERVER>'
$serverPath = "\\$server\adconfig\lcerts\domain\wc"
$testFile = Join-Path -Path $serverPath -ChildPath 'cert.pfx'
$localPath = 'c:\certs\wc'
$date = Get-Date -Format yyyyMMdd
$timespan = New-TimeSpan -Hours 1 -Minutes 1
$oldfolder = "c:\certs\old\$date"
# check if this output path exists. If not, create it
if (!(Test-Path -Path $oldfolder -PathType Container)) {
Write-Host "Creating folder '$oldfolder'"
New-Item -ItemType Directory -Path $oldfolder | Out-Null
}
Write-Host "testing variables..."
Write-Host "date = $date`r`nfolder path to create = $oldfolder`r`ntimespan = $timespan"
# test the LastWriteTime property from the cert.pfx file on the server
$lastwrite = (Get-Item $testFile).LastWriteTime
if (((Get-Date) - $lastwrite) -gt $timespan) {
#older
Write-Host "Nothing to update."
}
else {
#newer
Write-Host "Newer cert(s) available; copying all from '$localPath' to '$oldfolder'"
Copy-Item -Path $localPath -Filter '*.pfx' -Destination $oldfolder
Copy-Item -Path $serverPath -Filter '*.pfx' -Destination $localPath -Force
}

Powershell: You cannot call a null-valued expression

Hello Stack Overflow Community,
at the moment I'm struggling with this code (it's not that beautiful):
$filepath = "C:\inetpub\logs\LogFiles"
$filearchivepath = "C:\inetpub\logs"
$daystoarchive = 1
$_ = "";
function create-7zip([String] $aDirectory, [String] $aZipfile){
#change the path where you downloaded the 7z exe
[string]$pathToZipExe = "C:\Users\kschweiger\Downloads\7za.exe";
[Array]$arguments = "a", "-tzip", "$aZipfile", "$aDirectory";
& $pathToZipExe $arguments;
}
#Create a new folder with the specific date
$ArchiveFolder = (Get-Date -Format dd.MM.yyyy) + " - Logs-Archive"
if(Test-Path "$filearchivepath\$ArchiveFolder"){
Write-Host "Folder already exists!"
}else{
New-Item -Path $filearchivepath -Name $ArchiveFolder -ItemType directory
}
#Save alle files older than X days into $Files
$Files = Get-ChildItem -Path $filepath -Recurse | where {$_.LastWriteTime -lt (Get-Date).AddDays(-$daystoarchive)}
#Copy/Move files and keep folder structure
foreach ($File in $Files){
$NewPath = $File.DirectoryName.Replace($filepath,"")
if (!(Test-Path "$filearchivepath\$ArchiveFolder\$NewPath"))
{
New-Item -Path "$filearchivepath\$ArchiveFolder\$NewPath" -ItemType Directory
}
$File | Copy-Item -Destination "$filearchivepath\$ArchiveFolder\$NewPath"
}
#Compress folder
if(Test-Path "$filearchivepath\$ArchiveFolder.zip"){
Write-Host "Archive-File already exists!"
}else{
#[IO.Compression.ZipFile]::CreateFromDirectory("$filearchivepath\$ArchiveFolder","$filearchivepath\$ArchiveFolder.zip")
create-7zip "$filearchivepath\$ArchiveFolder" "$filearchivepath\$ArchiveFolder.zip"
#Delete Folder
Remove-Item -Path "$filearchivepath\$ArchiveFolder" -Recurse -Force
}
The code works. but I also get a error message called:
You cannot call a null-valued expression
How can I resolve this?
Get-ChildItem by default returns files and folders. If you need only files, you should use -File. Otherwise, your $Files will contain folders too (as they have LastWriteTime property).
If you try to run .DirectoryName.Replace($filepath,"") on a folder, it'll return such error as you cannot run replacing on $null.
Update: for PowerShell 2.0 you can use | where { ! $_.PSIsContainer } (source)
How can I troubleshoot it by myself?
In your error you can see which line is broken:
$NewPath = $File.DirectoryName.Replace($filepath,"")
All you have to do to troubleshoot such situations is to list all the involved variables and check their values. You could do it like this:
$File
$File.DirectoryName
Pause
$NewPath = $File.DirectoryName.Replace($filepath,"")
Using Pause can be useful as it'll wait for you to press Enter before continuing.

Organize files using PowerShell using path as variables?

I have a script that reorganizes files in C:\Year\Month\"StoreFiles" to "C:\Store\Date\"StoreFiles" based on modified date.
#Variables
$StoreName = "aStore"
$SourceDir = "C:\Source"
$TargetDir = "C:\$StoreName"
# Create Folder based on Store List
if(-Not (Test-Path -Path $TargetDir)) {
New-Item -ItemType Directory -Path $TargetDir
}
# Search & create folders based on date
Get-ChildItem "$SourceDir\*$StoreName*" -Recurse | ForEach-Object {
$x = $_.LastWriteTime.ToShortDateString()
$new_folder_name = Get-Date $x -Format MMM-yyyy
$des_path = "$TargetDir\$new_folder_name"
if (Test-Path $des_path) {
Copy-Item $_.FullName $des_path
} else {
New-Item -ItemType Directory -Path $des_path
Copy-Item $_.FullName $des_path
}
}
Works great however the modified date isn't ideal. Can I use the original folder path of "C:\Year\Month\"StoreFiles" and use it as dates for the new output?
In a sense I am trying to do the following:
"C:\Year\Month\"StoreFiles" to "C:\Store\Month-Year\"StoreFiles"
Maybe I should assign the folder path as a variable and use it accordingly for the new output?
Or is there another way I should think about doing this.
try Something like this
$dirroot="C:\temp\Root"
$store="C:\store"
Get-ChildItem $dirroot -file -Recurse |
where FullName -match ([Regex]::Escape($dirroot) + "\\\d{4}\\\d{1,2}\\" + [Regex]::Escape($_.Name)) |
% {
$elements=$_.FullName.Replace($dirroot, '').Split('\')
New-Item -ItemType Directory -Path "$store\$($elements[2])-$($elements[1])" -Force
Copy-Item $_.FullName "$store\$($elements[2])-$($elements[1])\$($elements[3])"
}
Cann't you use something like this?
$DateInfo = '' | select-object -Property 'Year', 'Month'
$File = 'c:\2014\may\filename.txt'
$TopFolderpath = [io.Path]::GetDirectoryName($File)
$TopFolderName = [io.Path]::GetFileName($TopFolderpath)
$DateInfo.Month = $TopFolderName
$Subfolderpath = [io.Path]::GetDirectoryName($TopFolderpath)
$SubFolderName = [io.Path]::GetFileName($Subfolderpath)
$DateInfo.Year = $SubFolderName
$DateInfo