I have a folder D:/Tests on a Windows machine, it stores folders that are created every day. I need code that runs with ansible on a linux machine that will delete all folders except the last three created ones. I've dug through dozens of articles in stackoverflow, but most of these issues are solved using bat files. For me, this option is not suitable. From what I found, here is the most similar to what I need:
Get-Childitem D:\Downloads_D -recurse | where {($_.creationtime -gt $del_date) -and ($_.name -notlike "*dump*" -and $_.name -notlike "*perform*")} | remove-item
But my knowledge of Powershell is not enough to edit it so that it performs my task.
Is there any way to achieve my goal using ansible modules, a Windows command line command, or a Powershell command?
For powershell, you could do the following:
Get-ChildItem -Path D:\Downloads_D -Directory | Sort-Object -Property CreationTime | Select-Object -SkipLast 3 | Remove-Item
Explanation
Filter directories using -Directory from Get-ChildItem
Sort directories by CreationTime property using Sort-Object
Skip last 3 directories using Select-Object and -SkipLast 3. This ensures the 3 most recently created directories are not removed.
Pipe to Remove-Item to remove the directories
Related
I have been looking around for this seemingly simple answer but finding nothing applicable. I have a file named "foo.txt" which might be found in multiple locations on my C drive. How do I form a PS command that results in a list of lines which contain only the full directories (not the file name itself). This would be a very simple matter in a Unix Bash shell but I cannot see it in PS. The closest I could get was the following:
Get-ChildItem -Path C:\ -Recurse -ErrorAction SilentlyContinue -Filter foo.txt
But the format of the output is not what I am looking for. I would like the output to be a simple one-directory-per-line output of the absolute directories which contain a "foo.txt" file (not just the lowest directory).
I found the format that I was looking for:
Get-ChildItem -Path C:\ -Recurse -ErrorAction SilentlyContinue -Filter foo.txt | Format-Table Directory -AutoSize -HideTableHeaders
Format-Table is the secret sauce, it appears. Without -AutoSize it clips long paths and adds three periods.
So at the company I am currently doing my internship at, they have about 20 'technical laptops' that have company-specified software. They are located in the C:\ directory.
For example:
aaa.exe is located at C:\aaa\aaa.exe
bbb.exe is located at C:\bbb\bbb.exe
What I actually need is a .ps1 script to show these specific executables in a list.
What I have so far is:
Get-ChildItem C:\ -recurse | where {$_.extension -eq ".exe"}
Now, I believe it's just edit the search query because this gives me all the .exe files on the C:\ drive and I just need aaa and bbb.
FYI: I need the script so that I can use it to monitor zabbix agents and see if the specific software is on the computer so I can run this script on the Zabbix Server.
You are looking for the -include parameter:
Get-ChildItem C:\ -recurse -include "aaa.exe", "bbb.exe"
#Martin Brandl has already answered your first question. For the second part of your question, you can do something like this -
$AllDrives = Get-PSDrive -PSProvider 'FileSystem'
foreach ($drive in $AllDrives)
{
Get-ChildItem -path $drive.Root -recurse -include "aaa.exe", "bbb.exe"
}
Or you can do it in one line -
Get-PSDrive -PSProvider 'FileSystem' | % {Get-ChildItem -path $_.Root -recurse -include "aaa.exe", "bbb.exe"}
You can change the -PSProvider parameter if your executables are on other drives other than FileSystem drives.
I am looking for a simple (if possible) way in powershell to check if a directory contains at least 1 other directory.
$dir = '.' # specify the directory to investigate
$hasAnySubdir = (Get-ChildItem -Force -Directory $dir).Count -gt 0
-Directory (PSv3+) ensures that Get-ChildItem only enumerates sub-directories, and -Force ensures that even hidden subdirectories are included.
I was trying to recursively list using ls all the *.py files in a directory in Windows PowerShell. It didn't work. I checked up on the man page and then online page that -Recurse flag doesn't accept wildcards so *.py wouldn't work.
I want to know whether there is a simple in-built way to recursively list the files of a particular file extension in a directory using Windows PowerShell 2.0?
I am a newbie in PowerShell and don't want to indulge in Shell scripting at this stage. So please recommend in-built commands, flags, etc. only, if any.
By commands I means the in-built keywords of the PowerShell. I am not sure if that is proper vocabulary for PowerShell.
Use the Filter parameter:
ls $path -filter *.py -recurse
This will do the trick for you.
gci -Recurse | ? {$_.name -match ".py"}
or
gci -Recurse -Include *.py
ls is an alias for Get-ChildItem. (So is dir and gci). A simple Google will give you all kinds of examples but the thing to know is -include (or -exclude) are built in parameters that will show (or not show) file types you are looking for. An additional parameter, -filter, can also be used for partial file types. The switch parameter -recurse checks the contents of subfolders in the directory as well. Example01:
gci -path \$computername\$directory -Include *.py -recurse
Example02:
gci -path \$computername\$directory -Filter *.py -recurse
I like to suppress errors so a full example would look like this:
gci -path \Svr01\C$ -Include *.py -recurse -erroraction SilentlyContinue
I don't see how anybody would have got this working at any time.
gci -recurse works fine and lists all
gci -filter *.txt works fine, lists all .txt files but does not recurse
gci -filter *.txt -recurse returns either only .txt files from root or nothing.
It seems to apply the *.txt filter to the directory names therefor seeing no directories and thus does not recurse at all.
I'm working on learning Windows PS - but until than I need some help writing a quick command:
I have a directory of directories, each directory has a unique name.
I need to rename all files within each of these directories to their parents name! As follows:
Current Structure:
/pdfdirectory/pdf_title_directory/filename.pdf
/pdfdirectory/pdf_title_directory123/filename.pdf
After shell script:
/pdfdirectory/pdf_title_directory/pdf_title_directory.pdf
/pdfdirectory/pdf_title_directory123/pdf_title_directory123.pdf
Thanks!
With good faith that you are learning Powershell and will try out stuff:
gci .\test -recurse | ?{ -not $_.PsIsContainer } |
%{rename-item -path $_.fullname -newname ($_.Directory.Name + $_.Extension)}
Of course, the above will fail it there is more than one file in the directory.
To understand the above learn basic Powershell commands like gci ( alias for Get-ChildItem) and Powershell pipeline concepts.
It's worth noting that you can pipe the output from Get-ChildItem directly into Rename-Item, you don't need a foreach. Also, and this is the clever part, the -NewName parameter value can be a script block that yields the new name. This script block can use $_ to refer to the file object that is currently being processed.
So you could do something like this:
dir -Recurse -Include filename.pdf | ren -NewName { "$($_.Directory.Name).pdf" }
(I think it was Keith Hill that made me aware of this trick.)