I am using a Powershell Script which should create a file that includes the Directory-Order (folder, subfolder, files, etc.):
$path = "golf.de/dgv"
Get-ChildItem -Path $folder -recurse | sort Directory, Name| format-Table -auto $path, Directory, Name | Out-File C:\Users\J.Kammermeier\Desktop\Johannes\testtext.txt
until now the output looks like this
C:\Users\J.Kammermeier\Desktop\Johannes Test-Datei1.txt
C:\Users\J.Kammermeier\Desktop\Johannes Test-Datei2.txt
C:\Users\J.Kammermeier\Desktop\Johannes\Sonstige Datein\Musik WACKEN.txt
but I need it in this order:
.../Johannes Test-Datei1.txt
...Johannes\Sonstige Datein\Musik WACKEN.txt
How to achieve it?
You'll have to mangle the Directory property a bit, using Select-Object and calculated properties:
# Set the path and folder property
$path = "golf.de/dgv"
$folder = "C:\Users\J.Kammermeier\Desktop\Johannes"
# Get the name of the parent folder (the part we want to remove)
$basePath = (Get-Item $folder).Parent.FullName
# Retrieve the files
$files = Get-ChildItem -Path $folder -Recurse
# Select the Name property and then two calculated properties, "Directory" and "Path"
$files = $files |Select-Object #{Name="BaseURL";Expression={"$path"}},
#{Name="Directory";Expression={$_.Directory.FullName.Substring($basePath.Length - 1)}},
Name
# Sort them
$files = $files |Sort-Object Directory, Name
# Formatted output to file
$files | Format-Table -AutoSize | Out-File C:\Users\J.Kammermeier\Desktop\Johannes\testtext.txt
From the details, I guess that you're trying to audit the files for a website, you could combine the Path and Directory properties and fix the back slashes with -replace:
#{Name="URLPath";Expression={"$path/" + $($_.Directory.FullName.Substring($basePath.Length - 1) -replace "\\","/")}}
Related
I have 30 folders. Each folder contains 22 .text files. I am trying to get the filenames and row count of each .text files and output it in a .csv file, appending the name of the .csv file with the name of each subfolder.
The script I made works but it will pull all the .text files from all subfolders and output it in a single .csv file.
Any idea how I can create one .csv file per subfolder ?
$results = Get-ChildItem "C:\Users\testserver\Documents\logfiles\*.txt" -Recurse | % { $_ | select name, #{n="lines";e={get-content $_ | measure-object -line | select -expa lines } } } | Select-Object name, lines
$results | Export-Csv "C:\Users\testserver\Documents\results.csv" -notype
Use the Group-Object cmdlet to process the files grouped by the directory they reside in:
$inDir = 'C:\Users\testserver\Documents\logfiles'
$outDir = 'C:\Users\testserver\Documents'
Get-ChildItem -File -Recurse -Filter *.txt $inDir |
Group-Object DirectoryName |
ForEach-Object {
$outFile = Join-Path $outDir "results-$(Split-Path -Leaf $_.Name).csv"
$_.Group |
Select-Object Name, #{ n="Lines"; e={ (Get-Content $_.FullName | Measure-Object -Line).lines } } |
Export-Csv -NoTypeInformation $outFile
}
The above creates output files such as results-foo.csv in $outDir, where foo is the name of a subdirectory containing *.txt files.
Note that the assumption is that no two subdirectories in the target $inDir directory tree have the same name; more work is needed if you need to handle such collisions, such as reflecting the relative paths in the file name, with \ replaced with a substitute char.
Can a wildcard be put in a folder name mask? Or is it necessary to run Get-ChildItem twice, one for the direcdtories and a second for the path? Even with the code below, I'm getting no directories returned.
I think this post shows how to do it with the older syntax:
$folderName = "c:\BizTalk\Vendors\*\AS2FilesReceived\"
$folderMask = "$folderName\*.*"
$dirs = Get-ChildItem -Path $folderName -Recurse -Directory
Write-Host "Number of Matching Directories = $($dirs.Count)"
$dirs
#$files = $dirs | %{ Get-ChildItem -Path $folderMask -Filter "*.*" -Exclude "*997*.*" -File} | Where-Object {$_.CreationTime -gt (Get-Date).AddDays(-6)} | Sort-Object LastWriteTime -Descending
Get-ChildItem supports wildcards in the path, but the wildcard applies only to a single folder level, i.e. a pattern C:\foo\*\bar will find folders C:\foo\abc\bar and C:\foo\xyz\bar, but won't find a folder C:\foo\abc\xyz\bar. For the latter you need something like this:
Get-ChildItem 'C:\foo' -Filter 'bar' -Directory -Recurse
If you have just a single variable folder level and want only files from the given path (without recursion) you can do something like this:
Get-ChildItem 'C:\foo\*\bar\*' -File
If you also want all files in subfolders below bar use this:
Get-ChildItem 'C:\foo\*\bar' -File -Recurse
Assuming that you want to find and return info about all files in all AS2FilesReceived directories for each folder under Vendors, then this might help you...
#Find all AS2FilesReceived directories
$dirs= Get-ChildItem -Path 'C:\BizTalk\Vendors\*\AS2FilesReceived\' -Directory
#Return number of directories
"$($dirs.Count) directories found"
#Return list of directory names
$dirs | % {$_.Parent.Name}
#Return the full name of every text file under each directory
$dirs | % {Get-ChildItem -Path $_ *.txt} | % {$_.FullName}
Which returns...
3 directories found
Vendor1
Vendor2
Vendor3
C:\BizTalk\Vendors\Vendor1\AS2FilesReceived\Vendor1AS2File.txt
C:\BizTalk\Vendors\Vendor2\AS2FilesReceived\Vendor2AS2File.txt
C:\BizTalk\Vendors\Vendor3\AS2FilesReceived\Vendor3AS2File.txt
Ultimately, I just wanted the files, not sure if I had a typo or what, but now this works. It's possible I swithced from $folderMask to $folderName, or didn't have the *.* on the end of the $folderMask.
$folderMask = "c:\BizTalk\Vendors\*\AS2FilesReceived\*.*"
$files = Get-ChildItem -Path $folderMask -File
Write-Host "Number of Matching Files = $($files.Count)"
I am trying to search for 2 files in a directory tree and delete them. I want to keep the path of the file that had been deleted.
So far that's what I have:
#set the path to search for the file
$path = ".\"
#File name
$file = "GeneratedCode.cs"
$file2 = "TypedEnums.cs"
#Look for the file and delete every instance of it in all directories.
Get-Childitem $path -include $file -recurse | foreach ($_) {remove-item $_.fullname}
#Look for the file and delete every instance of it in all directories.
Get-Childitem $path -include $file2 -recurse | foreach ($_) {remove-item $_.fullname}
EDIT:
I forgot to mention that I want to delete every instance of the files.
I would store the result of the Get-ChildItem cmdlet to a variable lets say $filesToDelete. Then you could simple pipe the object to the Remove-Item cmdlet (you don't need the foreach there):
$filesToDelete = Get-Childitem $path -include $file -recurse
$filesToDelete | Remove-Item
i am trying to loop through all files no matter the type, in a folder, and change a string with one that is input by the user..
i can do this now, with the code below, but only with one type of file extension..
This is my code:
$NewString = Read-Host -Prompt 'Input New Name Please'
$scriptPath = split-path -parent $MyInvocation.MyCommand.Definition
$InputFiles = Get-Item "$scriptPath\*.md"
$OldString = 'SolutionName'
$InputFiles | ForEach {
(Get-Content -Path $_.FullName).Replace($OldString,$NewString) | Set-Content -Path $_.FullName
}
echo 'Complete'
How do i loop through the files, no matter the extension ?
so no matter if it is a md, txt or cshtml or some other, it will replace the string as instructed.
To get all the files in a folder you can get use Get-ChildItem. Add the -Recurse switch to also include files inside of sub-folders.
E.g. you could rewrite your script like this
$path = 'c:\tmp\test'
$NewString = Read-Host -Prompt 'Input New Name Please'
$OldString = 'SolutionName'
Get-ChildItem -Path $path | where {!$_.PsIsContainer} | foreach { (Get-Content $_).Replace($OldString,$NewString) | Set-Content -Path $_.FullName }
this will first get all the files from inside the folder defined in $path, then replace the value given in $OldString with what the user entered in when prompted and finally save the files.
Note: the scripts doesn't make any difference regarding if the content of the files changed or not. This will cause all files modified date to get updated. If this information is important to you then you need to add a check to see if the files contains the $OldString before changing them and saving.
I have a list of 350 folders and each folder has a file Access log. I need to search all 350 files under all 350 folders for a name "Hound" and display the name of the folders which contain the name "Hound" in their access log file.
Below is my code, can someone help me with what should be added here to get the desired output, please?
#List all the folders in C:\testfolder
$folders = (Get-ChildItem -Path "C:\testfolder" | Where-Object{$_.Attributes -eq "Directory"} | Select Fullname)
#looping all folders
Foreach ($folder in $folders)
{
#Here I need to look for the word "Hound" inside the Access.log file and if the word is there, it should display the name of the $folder which has the word
}
Here's a fairly basic way to do this:
Get-ChildItem -Path d:\testfolder -Recurse | Select-String -Pattern "Hound"
If you need to make sure that only files called access.log are searched then specify a filter:
Get-ChildItem -Path d:\testfolder -Include "access.log" -Recurse | Select-String -Pattern "Hound"