Powershell network drive Get-ChildItem issues - powershell

Essentially I'm trying to use PowerShell to find files with certain file extensions on a network drive created on or after June 1st of this year. I thought I could do that with the following statement:
Get-ChildItem NETWORKPATH*. -recurse -include .xlsx | Where-Object { $_.CreationTime -ge "06/01/2014" }
I run into 2 problems:
The command only returns files from the root and one folder on the network drive, there's over 100 folders on this network drive
The command returns 3 out of the 5 files created after 6/1/14 and one created well before my creation time date.
I have access to all of the folders on the network drive. When I run Windows 7 search it finds all of the files. It doesn't matter if I run Powershell as administrator or not. It doesn't matter if I run it from my machine (Windows 7) or from one of our 2008 servers. The network drive I'm trying to search through is on a 2003 file server. What am I doing wrong?

Make sure you add a wildcard to your Include parameter. Also you should never use strings for date comparison. See the example of why not here. Try the following:
$testDate = new-object DateTime (2014,06,01)
Get-ChildItem NETWORKPATH*. -recurse -include *.xlsx | Where-Object { $_.CreationTime -ge $testDate }
Also note that files and folders marked as hidden will not show up unless you add a -force to the get-childitem. Not sure if that is part of the issue or not.

gci -path PATH -recurse | where {$_.extension -match "xlsx"} was the silver bullet to all of this.

This is what I use.
$Extensions = '*.xlsx','*.csv','*.xls'
$path = 'Network path'
Get-ChildItem "$path" -Include $Extensions -Recurse -Force | where {$_.CreationTime -gt
[datetime]"10/05/2018"} | Select * | Export-Csv -Path C:\TestExcelfiles.csv -
NoTypeInformation | fl * #format-wide

Related

Powershell: Find Folders and Run Command in Those Folders

so trying to find a way to combine a couple of things the Stack Overflow crowd has helped me do in the past. So I know how to find folders with a specific name and move them where I want them to go:
$source_regex = [regex]::escape($sourceDir)
(gci $sourceDir -recurse | where {-not ($_.psiscontainer)} | select -expand fullname) -match "\\$search\\" |
foreach {
$file_dest = ($_ | split-path -parent) -replace $source_regex,$targetDir
if (-not (test-path $file_dest)){mkdir $file_dest}
move-item $_ -Destination $file_dest -force -verbose
}
And I also know how to find and delete files of a specific file extension within a preset directory:
Get-ChildItem $source -Include $searchfile -Recurse -Force | foreach{ "Removing file $($_.FullName)"; Remove-Item -force -recurse $_}
What I'm trying to do now is combine the two. Basically, I'm looking for a way to tell Powershell:
"Look for all folders named 'Draft Materials.' When you find a folder with that name, get its full path ($source), then run a command to delete files of a given file extension ($searchfile) from that folder."
What I'm trying to do is create a script I can use to clean up an archive drive when and if space starts to get tight. The idea is that as I develop things, a lot of times I go through a ton of incremental non-final drafts (hence folder name "Draft Materials"), and I want to get rid of the exported products (the PDFs, the BMPs, the AVIs, the MOVs, atc.) and just leave the master files that created them (the INDDs, the PRPROJs, the AEPs, etc.) so I can reconstruct them down the line if I ever need to. I can tell the script what drive and folder to search (and I'd assign that to a variable since the backup location may change and I'd like to just change it once), but I need help with the rest.
I'm stuck because I'm not quite sure how to combine the two pieces of code that I have to get Powershell to do this.
If what you want is to
"Look for all folders named 'Draft Materials.' When you find a folder with that name, get its full path ($source), then run a command to delete files of a given file extension ($searchfile) from that folder."
then you could do something like:
$rootPath = 'X:\Path\To\Start\Searching\From' # the starting point for the search
$searchFolder = 'Draft Materials' # the folder name to search for
$deleteThese = '*.PDF', '*.BMP', '*.AVI', '*.MOV' # an array of file patterns to delete
# get a list of all folders called 'Draft Materials'
Get-ChildItem -Path $rootPath -Directory -Filter $searchFolder -Recurse | ForEach-Object {
# inside each of these folders, get the files you want to delete and remove them
Get-ChildItem -Path $_.FullName -File -Recurse -Include $deleteThese |
Remove-Item -WhatIf
}
Or use Get-ChildItem only once, having it search for files. Then test if their fullnames contain the folder called 'Draft Materials'
$rootPath = 'X:\Path\To\Start\Searching\From'
$searchFolder = 'Draft Materials'
$deleteThese = '*.PDF', '*.BMP', '*.AVI', '*.MOV'
# get a list of all files with extensions from the $deleteThese array
Get-ChildItem -Path $rootPath -File -Recurse -Include $deleteThese |
# if in their full path names the folder 'Draft Materials' is present, delete them
Where-Object { $_.FullName -match "\\$searchFolder\\" } |
Remove-Item -WhatIf
In both cases I have added safety switch -WhatIf so when you run this, nothing gets deleted and in the console is written what would happen.
If that info shows the correct files are being removed, take off (or comment out) -Whatif and run the code again.

Powershell script which will search folders with regex and which will delete files older than XX

I need a powershell script ;
it must search some subfolders which folders names are starting with character between 1 and 6 (like 1xxxx or 2xxx)
and using the name of these folders as variable it must look under each folder for the *.XML files which are older than 30 min
and if it finds them it must delete it.
there may be more than one folder at same time, which are providing the same conditions so IMO using an array is a good choice. But I'm always open to other ideas.
Anybody can help me please ?
Basically I was using this before the need changes but now it doesnt help me.
powershell -nologo -command Get-ChildItem -Path C:\geniusopen\inbox\000\ready\processed | Where CreationTime -lt (Get-Date).AddDays(-10) | remove-item
Thank you
You can do something like the following and just remove -WhatIf if you are satisfied with the results:
$Time = (Get-Date).AddMinutes(-30)
Get-ChildItem -Path 'C:\MostCommonLeaf' -Recurse -File -Filter '*.xml' |
Where {$_.CreationTime -lt $Time -and (Split-Path $_.DirectoryName -Leaf) -match '^[1-6]' -and $_.Extension -eq '.xml'} |
Remove-Item -WhatIf
MostCommonLeaf would be the lowest level folder that could start as your root search node. We essentially don't want to traverse directories for nothing.
You could potentially make the script above better if you know more about your directory structure. For example, if it is predictable within the path where the 1xxx folders will be, you can construct the -Path parameter to use the [1-6] range wildcard. -Filter '*.xml' could also return .xmls files for example, so that's why there is additional extension condition in the Where.
Using -Recurse and -Include together generally results in much slower queries. So even if tempted, I would avoid a solution that uses those together.
If there are millions of files/directories, a different command construction could be better. Running Split-Path millions of times could be less efficient than just matching on the directory name, e.g. where {$_.DirectoryName -match '\\[1-6][^\\]*$'}.
I think you are looking for something like this:
$limit = (Get-Date).AddMinutes(-30)
$path = "C:\Users\you\xxx"
$Extension = "*.xml"
Get-ChildItem -Path $path -Filter $Extension -Force | Where-Object {$_.CreationTime -lt $limit} | Remove-Item
I haven't tested it though.
Keep in mind whether you need: $.CreationTime or $.LastWriteTime

Moving Current objects (For me Folders) to the parent of the directory their in using PowerShell

I am trying to search through folders on a share drive for subfolders with "*OutPuts" in the name. These folders should have folders in them but should not have files:
select fullname,#{N='SubDirectories';E={[boolean]($_ |
get-childitem -directory).count}},#{N='SubFiles';E={[boolean]($_ |
get-childitem -file).count}}
When these folders are found I want to move any folders from the output folder to the Project folder (Parent of its Parent). Example:
Starting Condition: C:\AllProjects\Projectfolder\outputs\SubProjectFolder
Wanted Outcome: C:\AllProjects\Projectfolder\SubProjectFolder
Here's the full Code:
code somewhat reformatted for readability ...
$folders=Get-ChildItem C:\AllProjects -recurse -Directory |
where {$_.name -like "*Outputs"} |
select fullname,
#{N='SubDirectories';E={[boolean]($_ |
get-childitem -directory).count}},
#{N='SubFiles';E={[boolean]($_ |
get-childitem -file).count}}
$folders
$folders |
where {$_.subdirectories -eq $true -and $_.subFile -eq $False} |
foreach {
get-childitem |
Move-Item $_ -destination $_.parent.parent}
When ever I run the code the following message comes up:
cmdlet Move-Item at command pipeline position 1
Supply values for the following parameters:
Path[0]:
I'm pretty new to PowerShell so if someone could help break this down for me and tell me what I'm supposed to put here that would be greatly appreciated. Thank you for your time.
UPDATE
*I've tried it with
-Path $_, -Path $_.PsPath, -Path $_.FullName.
I've even tried Get-Item. With the -Path though I now get a message that's a little different:
cmdlet ForEach-Object at command pipeline position 2 Supply values for the following parameters: Process[0]:

Powershell: Recursively search a drive or directory for a file type in a specific time frame of creation

I am trying to incorporate Powershell into my everyday workflow so I can move up from a Desktop Support guy to a Systems Admin. One question that I encountered when helping a coworker was how to search for a lost or forgotten file saved in an unknown directory. The pipeline I came up with was:
dir C:\ -Recurse -Filter *.pdf -ErrorAction SilentlyContinue -Force | Out-File pdfs.txt
This code performed exactly how I wanted but now I want to extend this command and make it more efficient. Especially since my company has clients with very messy file management.
What I want to do with this pipeline:
Recursively search for a specific file-type that was created in a specified time-frame. Lets say the oldest file allowed in this search is a file from two days ago.
Save the file to a text file with the columns containing the Filename, FullName(Path), and sorted by the created time in descending order.
What I have so far:
dir C:\ -Recurse -Filter *.pdf -ErrorAction SilentlyContinue -Force | Select-Object Name, FullName | Out-File *pdfs.txt
I really need help on how to create a filter for the time that the file was created. I think I need to use the Where-Object cmdlet right after the dir pipe and before the Select Object pipe but I don't know how to set that up. This is what I wrote: Where-Object {$_.CreationTime <
You're on the right track, to get the files from a specific file creation date range, you can pipe the dir command results to:
Where-Object {$_.CreationTime -ge "06/20/2017" -and $_.CreationTime -le "06/22/2017"}
If you want something more repeatable where you don't have to hard-code the dates everytime and just want to search for files from up to 2 days ago you can set variables:
$today = (Get-Date)
$daysago = (Get-Date).AddDays(-2)
then plugin the variables:
Where-Object {$_.CreationTime -ge $daysago -and $_.CreationTime -le $today}
I'm not near my Windows PC to test this but I think it should work!
See if this helps
dir c:\ -Recurse -Filter *.ps1 -ErrorAction SilentlyContinue -Force | select LastWriteTime,Name | Where-Object {$_.LastWriteTime -ge [DateTime]::Now.AddDays(-2) } | Out-File Temp.txt

Recurse with PowerShell's Get-ChildItem

This seems like it should be simple, and I'm sure it is, but I've not cracked it the best way it should be done.
I want to search through a folder structure returning folders which meet the following conditions.
Folders which contain .msi files, but don't include executable files.
Folders which contain .exe files, but don't include .msi files.
Folders which contain both exe and msi files.
Each of these will be piped to a column in a CSV file.
My problem is I can't work out how to effectively return folder names which include one file type, but exclude another. I know on paper this seems simple using -include *.msi, -exclude *.exe, etc., but a command such as gci -Recurse -Include *.msi -Exclude *.exe includes folders containing an msi and exe folder where I only want that folder containing msi's only to be returned.
I am using the following directory structure as a test
msi only
msi and exe
exe only
Does this make sense?
I was experimenting with | where directory -notcontains *.exe and all kinds of similar things, but none of them worked the way I wanted or expected.
Unfortunately include and exclude only work with the recurse parameter. You won't be able to do exclusion without recursion.
Here's an alternative.
$folders = dir -path ~ -recurse | ? {$_.PsIsContainer}
$folders | ForEach-Object {
$exe_files = $_ | dir -filter *.exe
$msi_files = $_ | dir -filter *.msi
$type = ''
if ($exe_files -and $msi_files) {$type = 'Both'}
if ($msi_files -and -not $exe_files) {$type = 'MSI_ONLY'}
if ($exe_files -and -not $msi_files) {$type = 'EXE_ONLY'}
if ($type) {
New-Object -TypeName PsObject -Property #{Path=$_.FullName;Type="$type"}
}
} | ConvertTo-Csv | Set-Content ~\out.csv