Windows file search within a search, how? App, script, GREP, powershell, notepad hack? - powershell

I am trying to search for folders created within a certain date range, then search for files with certain attributes in only those folders. I thought with Windows 8's "advanced query system" this would be a 2 minute job...it isn't!
Can anyone recommend an easy way to do this? I'm thinking along the lines of regular expressions i can input into AstroGrep, or a Notepad++ hack, as it's easy to copy folder paths from windows search into a text document.
Thanks!
EDIT: To clarify, I am trying to find files which were added to the system during a certain date range. Searching by file created/modified attributes does not help as these attributes are carried over when the file is moved. However a folder's date attributes do change when files are moved in and out. Therefore I need to search for folders by date, then (because of the huge number of files and subfolders) search within the resulting folders for my files.

You could use the Get-ChildItem cmldet to retrieve all directories during a certain date range (for example: Now and a Month ago):
$dateNow = Get-Date
$dateaMonthAgo = $dateNow.AddMonths(-1)
$directories = Get-ChildItem -Path 'C:\' -Directory -Recurse |
Where { $_.LastAccessTime -le $dateNow -and $_.LastAccessTime -ge $dateaMonthAgo }
Now you have all directories that matches the date range. You can iterate over them and search for your files:
$directories | Get-ChildItem -Filter 'yourFile.txt'

Related

How to search for a specific file name then move all files after that file to another folder using PowerShell

Let's say I have 10 PDF files in a folder named c:\Temp
1440_021662_54268396_1.pdf
1440_028116_19126420_1.pdf
1440_028116_19676803_1.pdf
1440_028116_19697944_1.pdf
1440_028116_19948492_1.pdf
1440_028116_19977334_1.pdf
1440_028116_20500866_1.pdf
1440_028116_20562027_1.pdf
1440_028116_20566871_1.pdf
1440_028116_20573350_1.pdf
In my search, I know I am looking for a file that will match a specific number, for example 19676803 (I'm getting the number to search for from a SQL Query I'm running in my script)
I know how to find that specific file, but what I need to be able to do is move all the files after the searched file has been found to another pre-defined folder. So using the 10 PDFs above as the example files, I need to move all the files "after" the file named 1440_028116_19676803_1.pdf to another folder. I know how to move files using PowerShell, just do not know how to do it after/from a specific file name. Hope that makes sense.
$batchNumCompleted = 'c:\Temp\'
$lastLoanPrinted = $nameQuery.LoanNumber
$fileIndex = Get-ChildItem -path $batchNumCompleted | where {$_.name -match $lastLoanPrinted}
Can anyone provide suggestions/help on accomplishing my goal? I'm not able to provide all code written so far as it contains confidential information. Thank you.
Use the .Where() extension method in SkipUntil mode:
$allFiles = Get-ChildItem -path $batchNumCompleted
$filesToMove = $allFiles.Where({$_.Name -like '*19676803_1.pdf'}, 'SkipUntil') |Select -Skip 1
Remove the Select -Skip 1 command if you want to move the file with 19676803 in the name as well

Powershell: Compare Last Modified to Specific Date and replace with correct Date

I'm still fairly new to powershell, so please bear with me.
I have 2 almost identical directories. Files and folders from the old directory were copied over to a new directory. However, during this transfer process, something happened to the last modified date. The files and folders in the new directory have incorrect last modified dates (ex: today).
Rather than re-doing the transfer process, which would take a long time, I'd like to write something in powershell that will compare the last modified dates of the two directories and correct the dates in the new directory.
I'd also like to check first if file/folder has been modified since the file transfer. There would be no reason to change the date on those files.
What I found from looking around and googling:
Link1 Link2 Link 3 Link 4
I know that I can get the last modified date of a file with:
(Get-Item $filename).LastWriteTime
where $filename is the file directory.
I also came across the following:
dir $directory | ? {$_.lastwritetime -gt "6/1/19" -AND $_.lastwritetime -lt "12/30/19"}
I know I can get information regarding files that were modified between 2 dates. This, I can tweak to make it so the "less than (-lt)" can be used to check files that were not modified past a certain date.
dir $directory | ? {$_.lastwritetime -lt `12/13/19'}
This accomplishes one of my goals. I have a means to check if a file has been modified past a certain or not.
I saw this for changing the value lastwritetime
$folder = Get-Item C:\folder1
$folder.LastWriteTime = (Get-Date)
and realized this was simply
(Get-Item $filename).LastWriteTime = (Get-Date)
Which I could modify to meet my goal of replacing the new file's last write time wit the old file's correct time:
(Get-Item $filename).LastWriteTime = (Get-Item $filename2).LastWriteTime
I suppose what I'm struggling with is kind of putting it all together. I know how to recurse through files/folders for copy-item or even Get-Childitem by adding the "recurse" parameter. But I'm having difficulties wrapping my head around recursively navigating through each directory to change the dates.
Thank you for your help.
You could do the following to compare the LastWriteTime property of the original files and folders to the copies, while keping in mind that files in the copy folder could have been updated since the last transfer date.
# set the date to the last transfer date to determine if the file was updated after that
$lastTransferDate = (Get-Date).AddDays(-10) # just for demo 10 days ago
# set the paths for the rootfolder of the originals and the rootfolder to where everything was copied to
$originalPath = 'D:\OriginalStuff'
$copyPath = 'E:\TransferredStuff'
# loop through the files and folders of the originals
Get-ChildItem -Path $originalPath -Recurse | ForEach-Object {
# create the full path where the copied file of folder is to be found
$copy = Join-Path -Path $copyPath -ChildPath $_.FullName.Substring($originalPath.Length)
# test if this object can be found
if (Test-Path -Path $copy) {
$item = Get-Item -Path $copy
# test if the item has not been updated since the last transfer date
if ($item.LastWriteTime -le $lastTransferDate) {
# set the timestamp the same as the original
$item.LastWriteTime = $_.LastWriteTime
}
}
}
Great job with what you've done so far.
Just put what you have into a foreach statement.
Foreach($item in (gci 'C:\Users\usernamehere\Desktop\folder123' -recurse)){
(Get-Item $item.FullName).LastWriteTime = (Get-Item "C:\Users\usernamehere\Desktop\folderabc\RandomFile.txt").LastWriteTime
}
We wrap the Get-Childitem command with the -recurse flag into parenthesis so that the command executes on it's own and becomes a collection for our foreach command to traverse. $item is the current item in the loop. We will want to use the .FullName property to know the full path to the file for the current item. With that said you will use $item.FullName together for the files you are going to set the date on.

File transfer from one folder to another

I was wondering if anyone can help me with this problem, of moving files from C: drive to a network drive.
So at work we have a machine that outputs .txt files. For example these files include data about pets, so in the folder I have hundreds of files that are named similar to dogs_123456_10062019.txt then cats_123457_10062019.txt.
Now the first number is a reference number than changes per .txt file that is created and the other is a date, as said I can have hundreds of these per day the reference and date is not important to the transfer as the file includes all this information anyway
Now I have a network folder structure of Y:dogs & Y:cats and wanted a automated script that transfers all dog & cat text files to the corresponding network drive.
The network drive name cannot be changed as it's used by a monitoring software that outputs graphs based on the information in the text file.
Is this possible? Hopefully I've explained myself
Cheers
If folder names match file names then you can do something like that:
$SourceFolderPath = "C:\Source\"
$DestinationFolderPath = "Y:"
$FileList = Get-ChildItem -Path $SourceFolderPath
foreach($File in $FileList){
$FolderName = ($File.Name | Select-String -Pattern ".+?(?=_)").Matches.Value
$File | Move-Item -Destination "$DestinationFolderPath\$FolderName"
}
If names of folders do not match file names, you would need to manually create a dictionary of what should go where and then translate those
The code above is obviously not an enterprise level stuff :)

Renaming files in bulk and in ascending order in CMD

I know this question was already asked by someone but I will ask again.
Can someone tell me how to rename in bulk and in ascending order if possible in CMD. I already tried renaming in powershell but to no avail. It only let me use once and I need to rename another folder files but to no avail. It didn't let it rename files in another folder. This is the code I use in powershell:
$i = 1
Get-ChildItem *.mkv | %{Rename-Item $_ -NewName ('Haikyuu - {0:D2}.mkv' -f $i++)}
I'm renaming my anime series per folder and some of my copies have 100+ videos. and somehow you could teach me what each code mean (the code that must use in CMD). The ones I've searched can't understand it in layman's term or doesn't tell the user how it's supposed to work. Thank you in advance. by the way, the folder is placed in an external drive.
so from the beginning:
$i= variable for storing the initial value 1
Get-ChildItem = is like "dir" which lists the files and folder under a certain path.
In this case, it is listing all the files which starts with anything but have the extension .mkv
* indicates wildcard.
| = pipeline which passes the output of the first command as an input of the next command.
% = ForEach-Object is iterating each object one by one coming from the pipeline.
$_= Current pipeline object . Here it is taking each object one by one and renaming it using Rename-Item
-NewName = is the parameter of the Rename-Item which asks for the new name to pass.
Hope it clarifies your need.
The reason why I can't rename my video files is there were [brackets] on the filename.
So I use this:
Get-ChildItem -Recurse -Include *.mkv | Rename-Item -NewName { $_.Name.replace("[","").replace("]","").replace("(","").replace(")","") }
Which on the same directories, I can access subfolders too to omit brackets and parethesis. then I proceed using the code above in the question to rename my files in every folder. The Reason why I'm doing the 'renaming' per folder is that, each folder is different anime series. but the code above is working.
if anyone can give me less code than repeating the 'replace' and concatenating it, I will gladly accept and choose that as the best answer. :)
If you use the parameter -LiteralPath for the source, no prior renaming is necessary.
%i = 1
Get-ChildItem *.mkv |
ForEach {Rename-Item -LiteralPath "$_" -NewName ('Haikyuu - {0:D2}.mkv' -f $i++)}
A hint on sorting, I hope the present numbering of the source files has a constant width, otherwise the result is mixed up as an alphabetic sort (which is inherent to ntfs formatted drives) will sort the number 10 in front of 2.
To check this append the parameter -whatif to the Rename-Item command

How to find folders efficiently with specific name using powershell?

I want to use powershell to search for folders with specific name in some path, I have this:
get-childitem -path $path -Recurse -Directory -filter $folderName |
foreach{
write-host $_.FullName
}
It works but it is very slow, because there are a lot of files to search for. The case I am dealing is that there are huge amount of files inside the folder I want to find itself. It is wasting time to check for all these files. So I am wondering if there is a way to not dig into this folder when the folder name matches what I want to search for. Cannot do it by removing -recurse tag because the folder I want to search is not necessarily just inside $path but maybe some levels down.
Thanks!
Assuming you have access to all folders in the path, you could use Directory.GetDirectories():
$recurse = [System.IO.SearchOption]::AllDirectories
[System.IO.Directory]::GetDirectories($path,$folderName,$recurse)