I need create this list to allow an other program to properly work. I use this code:
function analyse {
Param(
[parameter(Mandatory=$true)]
[String]$newPath
)
cd $newPath
dir | Foreach-Object {
$data = Get-Content -Path o:\******\public\ParcoursArborescence\Limitless\data.txt
if ($_.PsisContainer -eq $True) {
$testPath = $_.FullName + ";"
$name = $testPath
$testPath = $data -match [regex]::escape($testPath)
$testpath
if($testPath.Length -eq 0) {
$name | Out-File -Append "o:\******\public\ParcoursArborescence\Limitless\data.txt"
if ($_.FullName.Length -gt 248) {
"ecriture"
$result += $_.FullName + "`r"
} else {
"nouvelle analyse"
$_.Fullname
analyse $_.FullName
}
}
} else {
$testPath = $_.Directory.FullName + ";"
$name = $testPath
$testPath = $data -match [regex]::escape($testPath)
if($testPath.Length -eq 0) {
$name | Out-File -Append "o:\******\public\ParcoursArborescence\Limitless\data.txt"
$_.FullName.Length
if ($_.FullName.Length -gt 260) {
"ecriture2"
$result += $_.Directory.Name + "`r"
}
}
}
}
$result | Out-File -Append "o:\******\public\ParcoursArborescence\Limitless\bilanLimitless.txt"
}
But it takes hours and hours... I need to use this in thousands of folders. So, do you have any idea about how could it get faster ?
Maybe I'm oversimplifying things here, but why not list all the files at once, and test their FullName Length (PS 3.0 needed for the -File parameter of Get-ChildItem) ?
$maxLength = 248
Get-ChildItem $newPath -Recurse |
Where-Object { ($_.FullName.Length -gt $maxLength) } |
Select-Object -ExpandProperty DirectoryName -Unique |
Out-File "overlength_paths.txt"
For PS 2.0:
$maxLength = 248
Get-ChildItem $newPath -Recurse -File |
Where-Object { ($_.FullName.Length -gt $maxLength) -and (-not $_.PSisContainer) } |
Select-Object -ExpandProperty DirectoryName -Unique |
Out-File "overlength_paths.txt"
Related
The purpose of this code is to transfer files from one location to another and to log whether the transfer was a success or a failure.
Everything works except I am having issues with the log. I want the log to be in CSV format and there to be 3 columns: success/failure, from location, and to location. This is outputting the results all into rows with one column.
I've tried the Export-Csv option but that looks for objects/properties so only displays the length(I have strings too). Add-content works but there is only one column. Any suggestions?
#LOCATION OF CSV
$csv = Import-Csv C:\test2.csv
#SPECIFY DATE (EXAMPLE-DELETE FILES > 7 YEARS. 7 YEARS=2555 DAYS SO YOU WOULD ENTER "-2555" BELOW)
$Daysback = "-1"
#FILE DESTINATION
$storagedestination = "C:\Users\mark\Documents\Test2"
#LOG LOCATION
$loglocation = "C:\Users\mark\Documents\filetransferlog.csv"
$s = "SUCCESS"
$f = "FAIL"
$CurrentDate = Get-Date
foreach ($line in $csv) {
$Path = $line | Select-Object -ExpandProperty FullName
$DatetoDelete = $CurrentDate.AddDays($DaysBack)
$objects = Get-ChildItem $Path -Recurse | Select-Object FullName, CreationTime, LastWriteTime, LastAccessTime | Where-Object { $_.LastWriteTime -lt $DatetoDelete }
foreach ($object in $objects) {
try
{
$sourceRoot = $object | Select-Object -ExpandProperty FullName
Copy-Item -Path $sourceRoot -Recurse -Destination $storagedestination
Remove-Item -Path $sourceRoot -Force -Recurse
$temp = $s, $sourceRoot, $storagedestination
$temp | add-content $loglocation
}
catch
{
$temp2 = $f, $sourceRoot, $storagedestination
$temp2 | add-content $loglocation
}
}
}
All your | Select-Object -ExpandProperty are superfluous, simply attach the property name to the variable name => $Path = $line.FullName
Why calculate $DatetoDelete inside the foreach every time?
Output the success/fail to a [PSCustomObject] and gather them in a variable assigned directly to the foreach.
Untested:
$csv = Import-Csv C:\test2.csv
$Daysback = "-1"
$destination = "C:\Users\mark\Documents\Test2"
$loglocation = "C:\Users\mark\Documents\filetransferlog.csv"
$s = "SUCCESS"
$f = "FAIL"
$CurrentDate = Get-Date
$DatetoDelete = $CurrentDate.Date.AddDays($DaysBack)
$Log = foreach ($line in $csv) {
$objects = Get-ChildItem $line.FullName -Rec |
Where-Object LastWriteTime -lt $DatetoDelete
foreach ($object in $objects) {
$Result = $s
$sourceRoot = $object.FullName
try {
Copy-Item -Path $sourceRoot -Recurse -Destination $destination
Remove-Item -Path $sourceRoot -Recurse -Force
} catch {
$Result = $f
}
[PSCustomObject]#{
'Success/Fail' = $Result
Source = $sourceRoot
Destination = $destination
}
}
}
$Log | Export-Csv $loglocation -NoTypeInformation
I am trying to get the CSV output like below so that user can filter in excel.
Folder,Group,Permission
I:\Folder1,corp\group1,ReadData,ExecuteFile,Synchronize
I:\Folder1\Folder2,corp\group2,ReadData,ExecuteFile,Synchronize
Below is what is started with. Very inefficient and does not give the desired CSV output. Will appreciate any help.
$output_file = $(get-date -f MM-dd-yyyy_HH_mm_ss)+'.txt'
"{0},{1},{2}" -f "Folder","Groups","Permissions"| add-content -path $output_file
$file_content = ''
function GetFolders($path = $pwd)
{
if( $path -ne $null) {
$new_row = Get-ACL $path | select -ExpandProperty Access | Where-Object IdentityReference -Like "CORP*" | SELECT $path, IdentityReference, FileSystemRights | Format-Table -HideTableHeaders | Out-String
$fileContent += $new_row
$fileContent | add-content -path $output_file
foreach ($item in Get-ChildItem $path)
{
if (Test-Path $item.FullName -PathType Container)
{
Write-Output $item.FullName
GetFolders $item.FullName
$new_row = Get-ACL $item.FullName | select -ExpandProperty Access | Where-Object IdentityReference -Like "CORP*" | SELECT $item.FullName, IdentityReference, FileSystemRights | Format-Table -HideTableHeaders | Out-String
$fileContent += $new_row
$fileContent | add-content -path $output_file
}
}
}
}
GetFolders "J:\"
You were on the right path but went off-course a bit.
Set-Content -Path $FileName -Value 'Folder,Groups,Permissions'
(Get-Acl -Path $Path).Access |
Where-Object -Property IdentityReference -like 'corp*' |
ForEach-Object {
Add-Content -Path $FileName -Value "$Path,$($_.IdentityReference),$($_.FileSystemRights -replace '\s')"
}
To be a little more fancy (if you want to edit the code in the subexpressions or something of that nature)
$Val = {"$Path,$($_.IdentityReference),$($_.FileSystemRights -replace '\s')"}
... -Value (&$Val) ...
The problem with this code is that for each folder, I only get 1 group or 1 user depending on the folder (mostly the last one), while I want to get all the security groups, and members of the folder, for each folder in the drive.
$title = "ADPermissions.csv"
$title2 = "ADPermissions2.csv"
$ss =$Selection1 -replace '[\W]', ''
$subtitle = "HardDrive"+ $ss
$exclude = #("BUILTIN|NT AUTHORITY|EVERYONE|CREATOR OWNER|NT AUTHORITY\SYSTEM|SYSTEM")
$OutFile = ($Selection2+"\"+$subtitle+$title)
Write-Host = $OutFile
if(Test-Path $OutFile -PathType Leaf)
{
$result3 = [System.Windows.MessageBox]::Show("The file already exists in the selected path`n"+"Do you want to delete it and proceed ?",'File already exists','YesNoCancel','Exclamation')
if ($result3 = "Yes")
{
Remove-Item $OutFile
$Header = "Folder Path,IdentityReference,names"
$RootPath = $Selection
$Folders = dir $RootPath | where {$_.psiscontainer -eq $true}
#To the point:
try {
foreach ($Folder in $Folders){$ACLs = get-acl $Folder.fullname | ForEach-Object { $_.Access } | where {$_.identityreference -notmatch $exclude}
Foreach ($ACL in $ACLs){
$strAcls = $ACL.IdentityReference.ToString()
$strUsers=#()
$strNames=$strAcls.Remove(0,12)
$user = $(try {Get-ADUser $strNames} catch {$null})
if ($strNames -ne $null -and $user -eq $null) {
$A += Get-ADGroupMember -identity $strNames -Recursive | Get-ADUser -Property DisplayName | Select Name | Sort-Object Name
} else {
}
foreach ($env:USERNAME in $A){
$strUsers +=$env:USERNAME
}
$OutInfo = $Folder.fullname + "," + $ACL.IdentityReference + $strUsers
}
Add-Content -Value $OutInfo -Path $OutFile | sort-Object
}
}catch [System.IO.IOException] {
}
}
I:\Dropbox,GESCOEUROPE\GR_G-FCASB-INT-ALL#{Name=CAPPUCCILLI FEDERICO}
#{Name=De Fruyt Frederik}
I:\General,GESCOEUROPE\GR_G-FCASB-INT-ADMIN#{Name=CAPPUCCILLI
FEDERICO} #{Name=De Fruyt Frederik#{Name=VANDEWALLE MARIA}
#{Name=VANSTEELANDT LUCRECE}
I:\ICT,GESCOEUROPE\GR_G-FCASB-INT-ADMIN#{Name=CAPPUCCILLI FEDERICO}
#{Name=De Fruyt Frederik} #{Name=FREDERIK DE FRUYT (ADM)}
#{Name=GAILITE ZANETE} #{Name=Geldhof Francine} #{Name=GOEMAERE
GWENNY}
I:\PaymentFollow-Up,GESCOEUROPE\GR_G-FCASB-INT-ALL#{Name=CAPPUCCILLI
FEDERICO}
this is the output i get, as you see for each folder I have only 1
group, But thats incorrect because some folders have more than 1 group
I have a directory that our work order program dumps xml files into. I need to search those files for a specific string and then copy them to another location based on that string. I modified the below code from another post and while I don't get any errors it also doesn't work. I'm very much a scripting newbie so any help would be greatly appreciated.
[string] $FileDirectory = "D:\Temp";
[string] $OutputPath = "D:\Temp\Temp_NY";
[string] $OutputPath2 = "D:\Temp\TEMP_FL";
foreach ($FilePath in Get-ChildItem $FileDirectory | Select-Object -ExpandProperty FullName)
{
[string] $Header = Get-Content $FilePath -First 0
if ($Header -match 'PARTNER |TEST_NY') {
Copy-Item $FilePath $OutputPath
}
elseif ($Header -match 'PARTNER |TEST_FL*') {
Copy-Item $FilePath $OutputPath2
}
}
The header would be -First 1 (first line only). -First 0 returns nothing. Try:
$FileDirectory = "D:\Temp";
$OutputPath = "D:\Temp\Temp_NY";
$OutputPath2 = "D:\Temp\TEMP_FL";
Get-ChildItem $FileDirectory | ? { !$_.PSIsContainer } | ForEach-Object {
$FilePath = $_.FullName
$Header = Get-Content $FilePath -First 1
if ($Header -match 'PARTNER |TEST_NY') {
Copy-Item $FilePath $OutputPath
}
elseif ($Header -match 'PARTNER |TEST_FL*') {
Copy-Item $FilePath $OutputPath2
}
}
I'm trying to log data surrounding the renaming of files using the following script. The only problem is that the log file contains files that were not renamed due to 'access denied' errors when attempting to rename. I need to figure out how to only create log entries for files that were SUCCESSFULLY renamed or pipe the failed renames to a different log file. I'd also like the total number of files renamed listed at the top of the log file if at all possible(ie 'xxx files were renamed') I appreciate any suggestions for getting this to work using powershell v2.
$drivesArray = Get-PSDrive -PSProvider 'FileSystem' | select -Expand Root
foreach ($drive in $drivesArray) {
Get-ChildItem $drive | Where-Object {
$_.FullName -notlike "${Env:WinDir}*" -and
$_.FullName -notlike "${Env:ProgramFiles}*"
} | ForEach-Object {
Get-ChildItem $_.FullName -Recurse -ErrorAction SilentlyContinue
} | Where-Object {
-not $_.PSIsContainer -and
$_.Extension -notmatch '^\.(xxx|exe|html)$'
} | ForEach-Object {
$newName = $_.FullName + '.xxx';
Rename-Item -Path $_.FullName -NewName ($_.FullName + '.xxx') -ErrorAction SilentlyContinue
Add-Content c:\temp\renameLog.txt -Value $('{0} {1} {2} {3}' -f $(Get-Date),$_.fullname,$_.name,$newName )
}
}
Here is an example, untested of course.
$success = 0
$failed = 0
$drivesArray = Get-PSDrive -PSProvider 'FileSystem' | select -Expand Root
foreach ($drive in $drivesArray) {
Get-ChildItem $drive | Where-Object {
$_.FullName -notlike "${Env:WinDir}*" -and
$_.FullName -notlike "${Env:ProgramFiles}*"
} | ForEach-Object {
Get-ChildItem $_.FullName -Recurse -ErrorAction SilentlyContinue
} | Where-Object {
-not $_.PSIsContainer -and $_.Extension -notmatch '^\.(xxx|exe|html)$' -and $_.Name -notmatch '^renameLog.txt|^renameLog_failed.txt'
} | ForEach-Object {
try {
$newName = $_.FullName + '.xxx';
Rename-Item -Path $_.FullName -NewName ($_.FullName + '.xxx') -ErrorAction Stop
Add-Content c:\temp\renameLog.txt -Value $('{0} {1} {2} {3}' -f $(Get-Date),$_.fullname,$_.name,$newName )
$success ++
} catch [exception] {
Add-Content c:\temp\renameLog_failed.txt -Value $('{0} {1} {2} {3}' -f $(Get-Date),$_.fullname,$_.name,$newName )
$failed ++
$error.Clear()
}
}
}
Add-Content "c:\temp\renameLog.txt" -Value $("Total: " + $success)
Add-Content "c:\temp\renameLog_failed.txt" -Value $("Total: " + $failed)