I am cleaning up some log files and trying to copy it to the new folder that gets created here.
but it fails in the line:
$newpath = join-path $f.directoryname\Cleaned $($f.basename + "_new" + $f.extension)
if I remove the "\Cleaned" part in that line, it works fine. but it copies the cleaned file on the same folder, which is not good.
I am not sure if the way I pass that new folder with the directory name is wrong. How do I do it right?
Function IIS-CleanUp1($path,$file)
{
$f = get-item $path\$file1
$newpath = join-path $f.directoryname\Cleaned $($f.basename + "_new" + $f.extension)
Get-Content $f | ? { $_ -match $control -and $_ -notmatch '^\#'} | Out-File $newpath
}
Function Files($path)
{
$allfiles = Get-ChildItem($path) -name
New-Item -ItemType directory -Path $path\Cleaned
foreach ($file1 in $allfiles)
{
IIS-CleanUp1($path,$file)
}
}
$path1 = "C:\Temp\IIS_CCHECK_AUG\IIS_CCHECK_AUG_202"
Files $path1
Q2:
I like to delete the directory "Cleaned", if it is already there, just above this line.
New-Item -ItemType directory -Path $path\Cleaned
when I try the following it does not work.
Remove-Item $path\Cleaned -force
Any ideas.
Thanks again.
-T
I think you need to have two parameters to join-path. Like join-path C:\ users (note the space). So put every extra path as a separate argument.
You need to fix the first path by adding quotes and get the inside evaluated to add \Cleaned:
$newpath = join-path "$($f.directoryname)\Cleaned" $($f.basename + "_new" + $f.extension)
Related
I have a script that look for specific filenames, and copy those to another destination.
No problem here, what I need help with is to give each file a _date/time in the destinationfolder
Like the copied file file1 get the name file1_20220427
The script I have now is like below:
$search_folder = "H:\SOURCE"
$destination_folder = "H:\DEST"
$file_list = #("file1","file2")
foreach ($file in $file_list)
{
$file_to_move = Get-ChildItem -Path $search_folder | % { $_.FullName}
if ($file_to_move)
{
Copy-Item $file_to_move $destination_folder
}
}
Without modifying too much of your code, there isn't a need for a foreach loop as you can pipe directly to Copy-Item:
$search_folder = "H:\SOURCE\*"
$destination_folder = "H:\DEST\"
$file_list = "file1*","file2*"
Get-ChildItem -Path $search_folder -Include $file_list -File|
Copy-Item -Destination {
$destination_folder + ($_.BaseName + "_" + (Get-Date).ToString("yyyyMMdd") + $_.Extension)
}
This is doable since Copy-Item can accept a scriptblock where you can modify the destination path to include a concatenated result. All that's needed is to provide the destination path, the basename property to keep the beginning of the name, append the date in format of yyyMMdd, and the extension to keep the file type.
Also, take note of the use of -Include. This parameter can accept an array of names to search for where you would need to provide the full name (extension included), or part of it with a wildcard (asterisk -*) allowing us to get rid of the foreach statement.
The only issue when using -Include is that it's PowerShell's solution to providing a search filter and not a file system provider based one.
Therefore, the source path has to include an asterisk at the end of the folder path, or the use of -Recurse is needed.
Now, your file names should reflect file1_20220427,file2_20220427 and so on accordingly, in your destination folder.
EDIT: based on your question in the comments, you can just test against the path to see if a folder with that days date is there, create the folder if not, then just route the items there now instead; it will copy the item's there if it already exists as well.
$search_folder = "H:\SOURCE\*"
$destination_folder = "H:\DEST\"
$file_list = "file1*","file2*"
Get-ChildItem -Path $search_folder -Include $file_list -File |
Copy-Item -Destination {
$dateFormat = (Get-Date).ToString("yyyyMMdd")
$destPath = Join-Path -Path $destination_folder -ChildPath $dateFormat
if (-not(Test-Path -LiteralPath $dateFormat)) { New-Item -Path $destPath -ItemType "Directory" | Out-Null }
"$destPath\" + ($_.BaseName + "_" + $dateFormat + $_.Extension)
}
I've finally have given up googling and come here out of desperation. Go easy on me I'm fairly new to Powershell.
So, the objective of the code below was to first look through the source folder, then read through each .zip file and move to the directory specified by the value in the hashtable. Unfortunately, this is not how they want it to work anymore.
Now I need to retain the parent folder from source: for example "DAL" and then create the proceeding folders based on the file names and finally move each .zip to its file specified folder. Also, it needs to go through each folder under source which will be at least 20 other folders with a unique 3 character names.
$srcRoot = "C:\Cloud\source\dal"
$dstRoot = "C:\Cloud\Destination"
##$map = #{}; dir -recurse | ? { !$_.psiscontainer} | % { ##$map.add($_.name,$_.PSChildName) }
# DAT and DEV will have to be excluded from folder creation
$map = {
#AEODDAT_201901 = "AEOD\2019\01"
#AEOMDEV_201902 = "AEOM\2019\01"
#AEOYDAT_201902 = "AEOY\2019\01"
}
$fileList = Get-ChildItem -Path $srcRoot -Filter "*.zip*" -File -Force -Recurse
foreach ($file in $fileList)
{
#Go through each file up to mapped string
$key = $file.BaseName.Substring(0,14)
if ($key -in $map.Keys)
{
$fileName = $file.Name
$dstDir = Join-Path -Path $dstRoot -ChildPath $map[$key]
#create direcotory if not in path
if (-not (Test-Path -Path $dstDir))
{
mkdir -Path $dstDir
}
Write-Verbose "Moving $($file.FullName)"
if (Test-Path -Path (Join-Path -Path $dstDir -ChildPath $fileName))
{
#Write error if name exists
Write-Error -Message "File $fileName already exists at $dstDir"
#move path
} else {
Move-Item -Path $($file.FullName) -Destination $dstDir
}
}
}
So C:\Cloud\source\DAL\AEODDAT20190101.zip should create folders in C:\Cloud\Destination\DAL\AEOD\2019\01\AEODDAT20190101.zip would be my desired output.
Welcome, Matt! (no pun intended) One of the habits I have in similar situations with destination folders is to Set-Location $dstRoot and create folders from the relative path. You can execute New-Item with the relative path and the syntax is simpler. For example, your If statement could look like this and it would work the same way (with a slightly different error message):
if ($key -in $map.Keys){
Set-Location $dstRoot
New-Item -ItemType Directory $map[$key] -ErrorAction Ignore #won't raise an error if it exists
Write-Verbose "Moving $($file.FullName)"
#this will raise an error if the file already exists, unless you specify -Force
Move-Item "$($file.FullName)" $map[$key]
}
EDIT: Found 2 issues.
$map is a Hashtable literal that should be preceded with #:
$map = #{
AEODDAT20190101 = "AEOD\2019\01"
You were missing the last character of the base file name by taking only the first 14 characters. AEODDAT2019010 didn't match AEODDAT20190101. This should fix it:
$key = $file.BaseName.Substring(0,15)
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.
I have thousands of files spanning 5 years which I would like to move into year/month folders. The file names all end with
_yyyy_mm_dd_wxyz.dat
I'm looking for ideas on how I can generate such file folders and move the files into the appropriate folders yyyy/mm using the windows command shell.
You'll need a Regular Expression with (capture groups) to extract year/month from the filename.
Assuming the year/month folder should be placed directly in files parent location.
untested with -Version 2
## Q:\Test\2018\07\23\SO_51485727.ps1
Push-Location 'x:\folder\to\start'
Get-ChildItem *_*_*_*_*.dat |
Where-Object {$_.BaseName -match '_(\d{4})_(\d{2})_\d{2}_[a-z]+$'} | ForEach-Object {
$TargetDir = "{0}\{1}" -f $Matches[1],$Matches[2]
if (!(Test-Path $TargetDir)){MD $TargetDir | Out-Null}
$_ | Move -Destination $TargetDir
}
Sample tree /f after running the script on my ramdriive:
PS A:\> tree /F
A:.
├───2017
│ └───07
│ test_2017_07_24_xyz.dat
└───2018
└───07
test_2018_07_24_xyz.dat
I have created this little quick and dirty script.
Things have been put in more variables than strictly needed, they could be combined in a single line, but I feel this adds clarity which I hope help you understand what happens.
As a note, I have used the date the item was last written to (created or edited).
If you want only the date the file was created and not the time the file was last edited, you could change LastWriteTime to CreationTime
#Load all files from the folder you wish to move on
$items = Get-ChildItem -Path "C:\SomeFolder\RestofPathToYourFiles"
foreach($item in $items) {
#Creates variables for year, month and day
$FolderYear = "$($item.LastWriteTime.Year)"
$FolderMonth = "$($item.LastWriteTime.Month)"
$FolderDay = "$($item.LastWriteTime.Day)"
#create variable with the new directory path
$NewPath = $item.Directory.FullName + "\" + $FolderYear + "\" + $FolderMonth + "\" + $FolderDay
#create variable with the new full path of the file
$NewFullPath = $NewPath + "\" + $item.Name
#test if the folder already is created, if not, create it
if((Test-Path -Path $NewPath) -eq $false) {
New-Item -Force -path $NewPath -Type Directory
}
#move the item to the new folder
Move-Item -Path $item.FullName -Destination $NewFullPath -Force
}
At the simplest, I'd do something like the following:
Determine the year and month related to a file
See if a folder exists already. If not, create it
Move the file
Example...
foreach ($file in $(ls .\stuff.txt)) {
$m = $file.LastWriteTime.Month.ToString("00")
$y = $file.LastWriteTime.Year
$dir = "{0}-{1}" -f $y, $m
New-Item -Name $dir -ItemType directory -ErrorAction SilentlyContinue | Out-Null
Move-Item -Path $file.Fullname -Destination $dir
}
I have a script that I'm working on that is intended to remove the temp folder (in C Disk), delete everything in temp, and then create a new temp folder. I have the script already created to delete everything, however I'm unsure of how you go about creating a new temp folder with Powershell. Was wondering if anyone might know how to create the new temp folder in Powershell.
#remove all temporary files
if($serverVersion.name -like "*2003*"){
$dir = "\\$server" + '\C$\temp'
}
elseif($serverVersion.name -like "*2008*"){
$dir = "\\$server" + '\C$\Windows\Temp'
}
$tempArray = #()
foreach ($item in get-childitem -path $dir){
if ($item.name -like "*.tmp"){
$tempArray = $tempArray + $item
}
}
for ($i = 0; $i -le $tempArray.length; $i++){
$removal = $dir + "\" + $tempArray[$i]
remove-item $removal -force -recurse
}
Am I correctly deleting the temp folder as well and, what would I have to do to create a new temp folder?
EDIT: I've updated my code based on what people have suggested, was wondering if this would have the desired effects and if there's a way to cut this down even further:
if($serverVersion.name -like "*2003*"){
$dir = "\\$server" + '\C$\temp'
remove-item $dir -force -recurse
new-item -path "\\$server" + '\C$\Windows\temp' -Type Directory
}
elseif($serverVersion.name -like "*2008*"){
$dir = "\\$server" + '\C$\Windows\Temp'
remove-item $dir -force -recurse
New-Item -Path "\\$server" + '\C$\Windows\Temp' -Type Directory
}
Use the New-Itemcmdlet to create the folder:
New-Item -Path "\\$server\admin$\Temp" -Type Directory
You can also use the 'md' alias (points to the mkdir function):
md "\\$server\admin$\Temp" -Force
UPDATE:
Here's what I would do: remove the directory. Check the $? variable (returns $true if the last command succeeded), if the command didn't completed successfully - create the Temp folder, otherwise there must have been an error and the Temp dir still exist.
Remove-Item -Path "\\$server\admin$\Temp" -Force -Recurse
if($?)
{
New-Item -Path "\\$server\admin$\Temp" -Type Directory
}
p.s. You could also add the Force switch to New-Item (or 'md') and create the folder regardless of the result of the previous command.
Why don't you simply remove temp folder with a recursive remove-item
# Remove recursively
Remove-Item -Path "\\$server\admin$\Temp" -Force -Recurse
# Create another one
New-Item -Path "\\$server\admin$\Temp" -Type Directory