Use Powershell to list the Fully Pathed Filenames on Individual Separate Lines? - powershell

If I execute:
Get-ChildItem *.ext -recurse
the output consists of a series of Directory sections followed by one or more columns of info for each matching file separated by said directory sections. Is there something like the Unix find command? In which each matching file name appears on a single line with its full relative path?

Get-Childitem by default outputs a view for format-table defined in a format xml file somewhere.
get-childitem | format-table
get-childitem | format-list *
shows you the actual properties in the objects being output. See also How to list all properties of a PowerShell object . Then you can pick and choose the ones you want. This would give the full pathname:
get-childitem | select fullname
If you want an output to be just a string and not an object:
get-childitem | select -expand fullname
get-childitem | foreach fullname

Resolve-Path with the -Relative switch can be used to display the relative paths of a set of paths. You can collect the full path names (FullName property) from the Get-ChildItem command and use the member access operator . to grab the path values only.
Resolve-Path -Path (Get-ChildItem -Filter *.ext -Recurse).FullName -Relative
Note: The relative paths here only accurately reflect files found within the current directory (Get-ChildItem -Path .), i.e. Get-ChildItem -Path NotCurrentDirectory could have undesirable results.

Get-ChildItem's -Name switch does what you want:
It outputs the relative paths (possibly including subdir. components) of matching files as strings (type [string]).
# Lists file / dir. paths as *relative paths* (strings).
# (relative to the input dir, which is implicitly the current one here).
Get-ChildItem -Filter *.ext -Recurse -Name
Note that I've used -Filter, which significantly speeds up the traversal.
Caveat: As of PowerShell 7.0, -Name suffers from performance problems and behavioral quirks; see these GitHub issues:
https://github.com/PowerShell/PowerShell/issues/9014
https://github.com/PowerShell/PowerShell/issues/9119
https://github.com/PowerShell/PowerShell/issues/9126
https://github.com/PowerShell/PowerShell/issues/9122
https://github.com/PowerShell/PowerShell/issues/9120

I am having some problem passing the path plus filename to a parser. There are about 90 files of 1 GB each involved in my task. Each of the file is contained in a folder of its own. All of the folders are contained under a parent folder.
Goal: Ideally, I would like to parse 20 files simultaneously for multitasking and continue to the next 20 until all 90 files are done.
This would mean that I would like to spawn some concurrent parsing of 20 files in a batch at any one given time. In carrying out the parsing, I would like to use measure-command to time the work from beginning to finish.
Script I have used:
Get-ChildItem –Path "E:\\OoonaFTP\\input\\Videos3\\" -Filter *.mp4 -recurse | select -expand fullname
Foreach-Object {
Measure-Command { "E:\OoonaFTP\Ooona_x64_ver_2.5.13\OoonaParser.exe -encode -dat -drm $_.FullName" } | Select-Object -Property TotalSeconds
}
===============================
I have this working batch script with a for statement but doing each iteration one after another. This is not what is the ideal case though. I would really like to accomplish this in PowerShell and with simultaneous tasks.
Could someone please suggest some ways by which I could accomplish this?
Thank you very much!

Thanks for the various suggestions. I'm curious that some of them lead to empty output in my Powershell (PSVersion: 5.1.18362.145).
I tried a number of these and, inspired by some of them, found the best answer for my case at the moment:
Get-ChildItem *.ext -recurse | Select-Object -property fullname
(When I made the window wide enough I got all the info I needed; in general I suppose I might need to do more to get the formatting I want.)

Related

Is there a way to grab data from this txt file in Powershell?

I am using Beyond Compare and I have gotten it to ouput if there are any differences into a txt file. However, I want to script this in powershell so that if there are no differences in files, the script will continue and do something else. However, I am not sure this is possible. I have looked through Select-String, but unsure if that will be able to do what I am looking for. Attached is what the txt file looks like when there are no differences as well as what it looks like when there are differences.
Is it possible to convert name, size, or modified in the txt file into a variable and then do a condition on whether it is null? Or is there is another way I can do what I am trying to achieve in Powershell? Thanks in advance.
If all you need to know is whether any differences were found, the following should do:
$noDiffs = '' -eq ((Get-Content -Raw report.txt) -split '\r?\n-+\r?\n')[1].Trim()
(Get-Content -Raw report.txt) -split '\r?\n-+\r?\n splits the entire input file by the the divider line (----...) following the table-header line, using a regex (regular expression).
[1] looks a the 2nd element of the resulting array, i.e., whatever comes after the divider line, trims any leading and trailing whitespace, and the result is tested for being the empty string.
With all respect to the question and the answer from #mklement0.
Using Beyond Compare in a PowerShell script is putting the cart before the horse.
There are a lot of cmdlets in PowerShell which would let you easily compare folders (and a lot more) without doing any text scraping.
As using Compare-Object togehter with Get-ChildItem for the given example:
Compare-Object (Get-ChildItem .\Test) (Get-ChildItem .\Test1) -Property Name, Length, LastWriteTime
If you want to do a recursive compare on the relative path, you can do:
Compare-Object (Get-ChildItem .\Test -Recurse -Name) (Get-ChildItem .\Test1 -Recurse -Name)
Note that the -Name parameter will only list relative path strings, if you also want to compare Length and LastWriteTime, You can do:
$TestFolder = 'C:\Test'
$Test1Folder = 'C:\Test1'
$TestFiles = Get-ChildItem $TestFolder -File -Recurse |
Select-Object *,#{N='RelativePath'; E={$_.FullName.SubString($TestFolder.Length)}}
$Test1Files = Get-ChildItem $Test1Folder -File -Recurse |
Select-Object *,#{N='RelativePath'; E={$_.FullName.SubString($Test1Folder.Length)}}
Compare-Object $TestFiles $Test1Files -Property RelativePath,Length,LastWriteTime

List out the .txt files which I modified in the previous five minutes

I managed to list out all the files which I modified in the last 5 minutes, but I only need the modified txt files. How can I get that?
Here is my code:
Get-ChildItem -Recurse| where-object{$_.LastWriteTime -gt (Get-Date).AddMinutes(-5)}
I know I should use -match, but I don't know where to put it and how to use it properly.
https://learn.microsoft.com/en-us/powershell/module/microsoft.powershell.management/get-childitem?view=powershell-6
has an example part way down that has -Path *.txt (and it also has an -Include *.txt -Exclude A* if you want examples of how to be more specific) - try those
As these things are options of Get-ChildItem they should go just before/after the -Recurse, i.e. before the pipe |

How can I use PowerShell or a cmd "dir" to get the contents of multiple, but similar paths?

For example, I want the contents of the "Last" folder in the structure below. The various path structures are identical except for the first two levels.
C:\zyx-wvu\abc\Level3\Last
C:\tsr-qpo\def\Level3\Last
C:\nml-kji\ghi\Level3\Last
In PowerShell I get close with:
Get-ChildItem -Path C:\*-*\*
...but it doesn't return any results (as in it never finishes) when I try:
Get-ChildItem -Path C:\*-*\*\Level3
Get-ChildItem -Path C:\*-*\*
will only show you what's in the second layer behind anything with a hyphen in c:\
aka it will show
c:\1-2\alpha
c:\1-5\beta
etc...
What you want is
Get-ChildItem -Path C:\*-*\*\*
or more likely you want
Get-ChildItem -Path C:\*-*\* -recurse
if you want to find paths with the SAME name... you could group them together, and pull out anything with more than one finding... you didn't ask very specifically what you wanted, but here's some ideas.
get-childitem -Path c:\*-*\*\* | group-object -property basename | where count -gt 1 | select -expand group

Copying files defined in a list from network location

I'm trying to teach myself enough powershell or batch programming to figure out to achieve the following (I've had a search and looked through a couple hours of Youtube tutorials but can't quite piece it all together to figure out what I need - I don't get Tokens, for example, but they seem necessary in the For loop). Also, not sure if the below is best achieved by robocopy or xcopy.
Task:
Define a list of files to retrieve in a csv (file name will be listed as a 13 digit number, extension will be UNKNOWN, but will usually be .jpg but might occasionally be .png - could this be achieved with a wildcard?)
list would read something like:
9780761189931
9780761189988
9781579657159
For each line in this text file, do:
Search a network folder and all subfolders
If exact filename is found, copy to an arbitrary target (say a new folder created on desktop)
(Not 100% necessary, but nice to have) Once the For loop has completed, output a list of files copied into a text file in the newly created destination folder
I gather that I'll maybe need to do a couple of things first, like define variables for the source and destination folders? I found the below elsewhere but couldn't quite get my head around it.
set src_folder=O:\2017\By_Month\Covers
set dst_folder=c:\Users\%USERNAME&\Desktop\GetCovers
for /f "tokens=*" %%i in (ISBN.txt) DO (
xcopy /K "%src_folder%\%%i" "%dst_folder%"
)
Thanks in advance!
This solution is in powershell, by the way.
To get all subfiles of a folder, use Get-ChildItem and the pipeline, and you can then compare the name to the insides of your CSV (which you can get using import-CSV, by the way).
Get-ChildItem -path $src_folder -recurse | foreach{$_.fullname}
I'd personally then use a function to edit the name as a string, but I know this probably isn't the best way to do it. Create a function outside of the pipeline, and have it return a modified path in such a way that you can continue the previous line like this:
Get-ChildItem -path $src_folder -recurse | foreach{$_.CopyTo (edit-path $_.fullname)}
Where "edit-directory" is your function that takes in the path, and modifies it to return your destination path. Also, you can alternatively use robocopy or xcopy instead of CopyTo, but Copy-Item is a powershell native and doesn't require much string manipulation (which in my experience, the less, the better).
Edit: Here's a function that could do the trick:
function edit-path{
Param([string] $path)
$modified_path = $dst_folder + "\"
$modified_path = $path.substring($src_folder.length)
return $modified_path
}
Edit: Here's how to integrate the importing from CSV, so that the copy only happens to files that are written in the CSV (which I had left out, oops):
$csv = import-csv $CSV_path
Get-ChildItem -path $src_folder -recurse | where-object{$csv -contains $_.name} | foreach{$_.CopyTo (edit-path $_.fullname)}
Note that you have to put the whole CSV path in the $CSV_path variable, and depending on how the contents of that file are written, you may have to use $_.fullname, or other parameters.
This seems like an average enough problem:
$Arr = Import-CSV -Path $CSVPath
Get-ChildItem -Path $Folder -Recurse |
Where-Object -FilterScript { $Arr -contains $PSItem.Name.Substring(0,($PSItem.Length - 4)) } |
ForEach-Object -Process {
Copy-Item -Destination $env:UserProfile\Desktop
$PSItem.Name | Out-File -FilePath $env:UserProfile\Desktop\Results.txt -Append
}
I'm not great with string manipulation so the string bit is a bit confusing, but here's everything spelled out.

Search using powershell

So I'm not sure if this can be accomplished, all of the answers I've seen deal with knowing the exact file name...but here it goes:
I want to search through a directory that has +-2,000 songs in it, but I don't want to have to know the whole file name (because some of them can get long and complicated). Here is an example of what I want:
I know I can display all of the contents of the directory doing this:
Get-ChildItem C:\My\Path\To\Songs\Here
But what I want to do (since that directory contains about 2,000 songs) is search so that I only have to enter a few words from the title and have only those songs that contain those words pop up. For instance:
If the full name of the file is "Everybody Dies Young" and I search for the keyword "Everybody" I want the following to pop up:
Everybody
Everybody Loves Everybody
I Can't Get With Everybody
etc
etc
etc
Is this possible to search keywords in a directory and return all filenames with those keywords? I run Windows 7 if that helps anybody at all...
Use the -Filter parameter
Get-ChildItem -Path C:\My\Path\To\Songs\Here -Recurse -File -Filter *Everybody*
Reference: Get-ChildItem
-Filter
Specifies a filter in the provider's format or language. The value of
this parameter qualifies the Path parameter. The syntax of the filter,
including the use of wildcards, depends on the provider. Filters are
more efficient than other parameters, because the provider applies
them when retrieving the objects, rather than having Windows
PowerShell filter the objects after they are retrieved from the
provider.
Update:
To get just the file paths you can extend it like
Get-ChildItem -Recurse -File -Filter *Everybody* | % {$_.FullName}
Or
Get-ChildItem -Recurse -File -Filter *Everybody* | Foreach-Object {$_.FullName}
by piping the files to a for each loop and extracting the full path.
if you want a filter more elabored you can do it:
Get-ChildItem -Recurse -File | where {$_.Name -like "*word1*" -and $_.Name -notlike "*word2*"} | select FullName