What is wrong with my script? Deletes all files -- Powershell - powershell-2.0

I want to delete files recursively, while keeping the seven most recent ones. The following script deletes all files, even though I specify the skip parameter.
$files = gci -path f:\inbox\test -recurse | where {!$_.PsIsContainer}
foreach ($file in $files) {sort creationtime -desc | select -skip 7 | remove-item -path $file.FullName -force}
This script doesn't do a damn thing:
gci -path f:\inbox\test -recurse | where {!$_.PsIsContainer} | foreach-object {sort creationtime -desc | select -skip 7 | remove-item -force }

try this
$files = gci -path f:\inbox\test -recurse | where {!$_.PsIsContainer} | sort creationtime -desc | select -skip 7
foreach ($file in $files) {remove-item -path $file.FullName -force}
or more simply
gci -path f:\inbox\test -recurse | where {!$_.PsIsContainer} | sort creationtime -desc |
select -skip 7 | remove-item -force

Related

Delete long name path folders older than 7 days

I need to make a script that it will be delete folders and files(all things), but only older than 7 days. I have a code, but it has a problem when path name is longer than 256 chars. One of the user has a many folders, name lenght equal 303 chars.
Below code works on Windows 10, but has problem on Windows 2008R2(.net 4.7.2) with \\?\....
Get-ChildItem -Path '\\?\c:\test\users' | ?{ $_.CreationTime -le $(Get-Date).AddDays(-7) } | Remove-Item -recurse -force
And that has problem with long path name:
Get-ChildItem D:\foler\folder\file | ?{ $_.CreationTime -le $(Get-Date).AddDays(-7) } | Remove-Item -Force -Recurse
Get-ChildItem D:\foler\folder\file | ?{ $_.CreationTime -le $(Get-Date).AddDays(-7) } | Remove-Item -Force -Recurse
Also I try with robocopy. So will be ok any script on powershell, .bat or .vbs.

Powershell - query servers with roles installed

I have a txt file with all the server names.
I want to query each server in the txt to see if RDS is installed. So far it works fine. But the export needs to have servername and the installed role. how can I pass the servername to the output file.
At the moment it is querying but only the installed. so with a 100 servers who really can tell which server has it installed and which doesnt>>>> PLEase help
Import-Module ServerManager
Get-Content W:\AllWindows.txt | ForEach-Object {Get-WindowsFeature -Name Remote-Desktop-Services} | Format-Table -Auto -wrap | Out-File -FilePath $csvfile
Try something like this:
Get-Content W:\AllWindows.txt | ForEach-Object { #(($_), (Get-WindowsFeature -Name Remote-Desktop-Services)) } | Format-Table -Auto -wrap | Out-File -FilePath $csvfile
I have worked it out:
Get-Content W:\windows2012.csv | Foreach-Object {{Get-WindowsFeature | where-object {$_.Installed -eq $True} | Export-Csv -Path "W:\output\$_.txt"}

powershell v2 - rename a file whose name matches a string containing a wildcard

I'm trying to create a script to rename a file that matches a given filename, with a wildcard character. e.g.
I have a folder containing the following files:
201412180900_filename_123.log
201412181000_filename_123.log
201412181100_filename_456.log
filename_789.log
I want to scan through this folder, and append the current time to the start of any file starting with the word 'filename'
I have the following so far:
$d = Get-Date -format "yyyyMMddHHmm"
$dir = "C:\test"
$file = "filename*.log"
get-childitem -Path "$dir" | where-object { $_.Name -like "$file" } | rename-item -path $_ -newname $d."_".$_.name
but it doesn't work.
As I see it the individual sections 'should' work from my reading of the documentation, but clearly something is wrong. If someone can point it out it would be appreciated.
We're getting closer. It would appear that -path in the rename-item section needs to be $dir$_ as $_ (seemingly) only contains the filename. (The get-help example suggests it needs to be the full path and filename)
If I take out the rename-item section and replace it with %{write-host $d"_"$_} it gives the correct new filename
However, simply placing this into rename-item section still doesn't update the filename.
rename-item -path $dir$_ -newname $d"_"$_
SUCCESS
the correct syntax appears to be:
get-childitem -Path "$dir" | where-object { $_.Name -like "$file" } | %{rename-item -path $dir$_ -newname $d"_"$_}
The missing element was the %{ ... } surrounding the rename-item section which enabled me to reference $_
$d = Get-Date -format "yyyyMMddHHmm"
$dir = "C:\test"
$file = "filename*.log"
get-childitem -Path $dir | where-object { $_.Name -like $file } | %{ rename-item -LiteralPath $_.FullName -NewName "$d`_$($_.name)" }
This should work, assuming that the errors were relating to "Cannot bind argument to parameter 'Path'", and the NewName string.
Issues included:
Not being able to reference $_ when not in a foreach style block (see here)
The Concatenation issue raised by #alroc
You could, instead of passing the pipeline object to a Foreach-Object, pass directly to the Rename-Item - but I'm unsure quite how to reference the name of the object for the -NewName parameter.
I don't recall . being a string concatenation operator in PowerShell (I may be wrong). Try this:
rename-item -path $_ -newname "$d_$($_.name)"
Or this
rename-item -path $_ -newname ($d + "_" + $_.name)
Or even this
rename-item -path $_ -newname ({0}_{1} -f $d,$_.name)
See the answers here
Yet another way to do it without using foreach or %, but a script block instead:
get-childitem -Path "$dir" -filter $file | rename-item -newname { $d + "_" + $_.name }
See the examples in the doc for rename-item: https://msdn.microsoft.com/en-us/powershell/reference/3.0/microsoft.powershell.management/rename-item There's a -replace operator too, but it can't use wildcards? Oh, you don't need wildcards:
get-childitem -Path "$dir" -filter $file | rename-item -newname { $_.name -replace 'filename',($d + '_filename') }

What is wrong with this script to create files in all subfolders?

I have a directory tree, consisting of several layers, within which I want to create 30 placeholder files, recursively in each folder.
The tree looks something like this:
--F:\inbox\test
----folder1
------subfolder1
------subfolder2
----folder2
------subfolder1
------subfolder2
----folder3
------subfolder1
------subfolder2
Here is what I have.
$folders = gci -path f:\inbox\test -recurse | where {$_.PsIsContainer}
foreach ($folder in $folders) {
1..30 | % { New-Item -Name "$_.txt" -Value (get-date).tostring() -Itemtype file -force}
}
This just creates 30 files in the root folder. I know I am missing something in my logic.
You're not telling new-item where to put the file, so it uses the current working directory. Fortunately, this is easliy fixed with the -Path parameter for the cmdlet.
$folders = gci -path f:\inbox\test -recurse | where {$_.PsIsContainer}
foreach ($folder in $folders) {
1..30 | % { New-Item -Path $folder.FullName -Name "$_.txt" -Value (get-date).tostring() -Itemtype file -force}
}

find a string in a textfile and replace it with the name of the parent folder

I have this issue where I must replace the string "121212" in all text files with the name of it's parent folder (e.g. if the parent folder is named "123456" than the string "121212" should be replaced with "123456")
I thought I figured out how to do this with the following commands:
PS E:\testenvironment> $parent=get-childitem -recurse | where {$_.FullName -match "[testenvironment]\\\d{6}$"} | foreach {$_.Name}
PS E:\testenvironment> $parent
123456
456789
654321
987654
PS E:\testenvironment> $files=get-childitem -recurse | where {$_.FullName -match "\\\d{6,6}\\AS400\\test3.txt$"} | foreach {$_.FullName}
PS E:\testenvironment> $files
E:\testenvironment\123456\AS400\test3.txt
E:\testenvironment\456789\as400\test3.txt
E:\testenvironment\654321\AS400\test3.txt
E:\testenvironment\987654\AS400\test3.txt
PS E:\testenvironment> foreach ($file in ($files)) {Get-Content "$file" | foreach-Object {$_ -replace "121212", "($name in ($parent))"} | set-content "$file"}
But I get this message :
Set-Content : The process cannot access the file 'E:\testenvironment\123456\AS400\test3.txt' **because it is being used by another process**.
At line:1 char:127
+ foreach ($file in ($files)) {Get-Content "$file" | foreach-Object {$_ -replace "121212", "($name in ($parent))"} | set-content <<<< "$file"}
+ CategoryInfo : NotSpecified: (:) [Set-Content], IOException
+ FullyQualifiedErrorId : System.IO.IOException,Microsoft.PowerShell.Commands.SetContentCommand
(... i receive this for every test3.txt file ofcourse ...)
I cannot figure out how to get the "current memory" into a new variable so, that the file (that would currently be in the memory) can be overwritten with the new data.
Provided all of your text files are in the directory structure you've posted, the following will get the job done:
get-childitem $testEnvPath -recurse -filter "*.txt" | foreach{
$content = Get-Content $_.fullname
#To get the file's grandparent directory name ($_.fullname -split '\\')[-3]
$content -replace "121212", ($_.fullname -split '\\')[-3] |
set-content $_.fullname
}
Note that to 'move' to the next file / directory in memory, the enumeration of those items must be inside of the foreach statement whereas you were enumerating them outside.
Hope that helps.

Resources