I need to check if files from input exists.
I split multiple inputs for example BWMDL.VML BWMDL.STA etc and write out files that are already in folder
I check if files from input are present in folder or not.
But I'm getting True, even if the file doesnt exists, also the output from test-path is printed twice, with different result.
Set-Variable -Name Files -Value (Read-Host "instert file name")
Set-Variable -Name FromPath -Value ("C:\Users\Desktop\AP\AP\parser\*.VML" , "C:\Users\Desktop\AP\AP\parser\*.STA")
Set-Variable -Name NameOfFiles (Get-ChildItem -Path $FromPath "-Include *.VML, *.STA" -Name)
Write-Host "FILES IN FOLDER:"
$NameOfFiles
Write-host "---------------------"
Write-host "FILES FROM INPUT: "
Splitted
Write-host "---------------------"
Write-host "FILE EXISTS: "
ForEach ($i in Splitted) {
FileToCheck
}
function Splitted {
$Files -Split " "
}
function FileToCheck {
Test-Path $FromPath -Filter $Files -PathType Leaf
}
For example I'm getting like this result
You are over complicating this.
Once you get the names of all files with extension .VML or .STA in an array, you do not have to use Test-Path anymore, since you know the files in array $NameOfFiles actually do exist, otherwise Get-ChildItem would not have listed them.
This means you can get rid of the helper functions you have defined, which BTW should have been written on top of your code, so before calling on them.
Try
$Files = (Read-Host "instert file name(s) separated by space characters" ) -split '\s+'
$FromPath = 'C:\Users\Desktop\AP\AP\parser'
# if you need to recurse through possible subfolders
$NameOfFiles = (Get-ChildItem -Path $FromPath -Include '*.VML', '*.STA' -File -Recurse).Name
# without recursion (so if files are directly in the FromPath):
# $NameOfFiles = (Get-ChildItem -Path $FromPath -File | Where-Object {$_.Extension -match '\.(VML|STA)'}).Name
Write-Host "FILES IN FOLDER:"
$NameOfFiles
Write-host "---------------------"
Write-host "FILES FROM INPUT: "
$Files
Write-host "---------------------"
Write-host "FILE EXISTS: "
foreach ($file in $Files) { ($NameOfFiles -contains $file) }
Output should look like
instert file name(s) separated by space characters: BWMDL.VML BWMDL.STA
FILES IN FOLDER:
BWMDL.STA
BWMDL.VML
---------------------
FILES FROM INPUT:
BWMDL.VML
BWMDL.STA
---------------------
FILE EXISTS:
True
True
Related
In a folder i have many files, they are sequential, type ABC001.csv,ABC002.csv,ABC003.csv and so on. Sometimes this sequence breaks, then there are missing files and I need to identify which of the sequence are missing in the folder manually, we have more than 700files.
Does anyone here know a power shell script to help me with this task?
If all files to be counted always have a naming format ABC<3-digit number>.csv, then you could do this:
# get an array of integer sequence numbers from the files
$sequence = (Get-ChildItem -Path 'D:\Test' -Filter 'ABC*.csv' -File).BaseName |
Where-Object { $_ -match '(\d{3})$' } | ForEach-Object { [int]$matches[1] } |
Sort-Object -Unique
# get the missing numbers (if any) and output filenames to be collected in $missingFiles
$missingFiles = Compare-Object $sequence (1..($sequence[-1])) -PassThru | ForEach-Object {
'ABC{0:D3}.csv' -f $_ # reconstruct the filename with the missing number
}
# output on screen
if (#($missingFiles).Count) {
Write-Host "Files missing:" -ForegroundColor Yellow
$missingFiles
}
else {
Write-Host "All files are in sequence" -ForegroundColor Green
}
Of course, change the rootpath of the files (here 'D:\Test') to your own
In this example,
The script is located in the same location as a folder named "Temp".
The "Temp" folder had files ABC001.csv through ABC717.csv.
Files ABC123.csv and ABC555.csv were deleted from "Temp" folder.
for ($i = 1; $i -lt 718; $i++) {
$FileName = $PSScriptRoot + '\Temp\ABC{0:d3}.csv' -f $i
if(-not (Test-Path -Path $FileName -PathType Leaf)) {
Write-Host "Missing $FileName"
}
}
Output when ran:
Missing 123
Missing 555
So I have an assignment where I have to create an PowerShell script that takes three parameters, "$foldername", "$filename" and "$number".
The script checks if the folder "$foldername" exists and if not, creates it. After that it creates as many new files named "$filename" as "$number" specifies. After that it reports how many files have been created and lists them.
What I have so far.
Param (
[string]$foldername,
[string]$filename,
$number=1
)
if ((Test-Path -Path $foldername) -ne $true) {
new-item -path $foldername -ItemType directory #if the folder doesn't exist, create it.
}
$new_file= $foldername+"\$_"+$filename #save the path and name of the new file to an variable
if ((Test-Path -Path $new_file* -PathType leaf) -eq $true) {
Write-Host "$filename already exists in $foldername"
break #if a file with a name that contains $filename in it exists in $foldername, break and do not create any new files.
}
$null=1..$number | foreach { new-item -path $foldername -name $_$filename } #create new files using foreach.
write-host ("Created $number new files") #tell the user how many files were created
Get-ChildItem -path $foldername | where-object Name -like *$filename* | format-table Name #show the created files in a table format, formatted by name
There are a few problems and scuffed solutions in this script, but the main problem is the creation of the new files. Since the name of the new files come from $filename, simply running the script like so:
./script.ps1 -foldername C:\users\example\testing -filename "test.txt" -number 5
Would not work since it tries to create 5 files named "test.txt" and will just return errors.
I sort of solved it by using "foreach" and naming the files $_$filename which creates
1test.txt
2test.txt
...
5test.txt
But I found out that the correct way would be:
test1.txt
test2.txt
...
test5.txt
The number should be running in the filename somehow, but I am not sure how to do that.
Bonus points if you figure out how to check if the $filename files already exist in the target folder.
It's good to use Test-Path however I don't see a need for it here, you can use $ErrorAction = 'Stop' so that if the folder exists the script would instantly stop with a warning message. On the other hand, if the folder is a new folder there is no way the files already exist.
Param (
[parameter(Mandatory)]
[string]$FolderName,
[parameter(Mandatory)]
[string]$FileName,
[int]$Number = 1
)
$ErrorActionPreference = 'Stop'
try {
$newFolder = New-Item -Path $FolderName -ItemType Directory
}
catch {
# If the folder exists, show this exception and stop here
Write-Warning $_.Exception.Message
break
}
$files = 1..$Number | ForEach-Object {
# If this is a new Folder, there is no way the files already exist :)
$path = Join-Path $newFolder.FullName -ChildPath "$FileName $_.txt"
New-Item -Path $path -ItemType File
}
Write-Host 'Script finished successfully.'
$newFolder, $files | Format-Table -AutoSize
EDIT: I might have missed the point where you want to create the files in the folder even if the folder already exists, in that case you could use the following:
Param (
[parameter(Mandatory)]
[string]$FolderName,
[parameter(Mandatory)]
[string]$FileName,
[int]$Number = 1
)
$ErrorActionPreference = 'Stop'
$folder = try {
# If the Folder exists get it
Get-Item $FolderName
}
catch {
# If it does not, create it
New-Item -Path $FolderName -ItemType Directory
}
$files = 1..$Number | ForEach-Object {
$path = Join-Path $folder.FullName -ChildPath "$FileName $_.txt"
try {
# Try to create the new file
New-Item -Path $path -ItemType File
}
catch {
# If the file exists, display the Exception and continue
Write-Warning $_.Exception.Message
}
}
Write-Host "Script finished successfully."
Write-Host "Files created: $($files.Count) out of $Number"
$files | Format-Table -AutoSize
Test-Path is returning true, or at least appears to be on folders that are empty if they are located in the same directory as folders returning true that are NOT empty.
I've tried adjusting wildcard locations, adding additional \ to change paths to see if I could reduce the number of returned folders, but I cannot. I assumed the foreach portion and Test-Path would individually check each folder and return a result, but it appears once it sees contents, all folders thereafter are returned as true.
[int]$subDay = Read-Host "Enter days to subtract"
$date0 = (Get-Date).AddDays(-$subDay).ToString("yy") +
((Get-Date).AddDays(-$subDay).DayOfYear).ToString("D3")
$date1 = (Get-Date).AddDays(-$subDay).ToString("yyyy") +
((Get-Date).AddDays(-$subDay).DayOfYear).ToString()
$path0 = ".\11"
$path1 = ".\12"
$path2 = ".\13"
$a = $path0, $path1, $path2
function Split {
Param ($split)
Split-Path -Parent $split |
Get-Item |
Select-Object -ExpandProperty Name |
Add-Content $archLog
foreach ($element in $a) {
if (Test-Path $element\$date1\"$date0*"\*) {
Split $element\$date1
Split $element\$date1\"$date0*"\*
} else {
Split $element\$date1
Write-Output "Folders do not exist or are empty." |
Add-Content $archlog
}
}
I expected the code to return folder name if it had contents, which it does. However, if an empty folder exists where a folder with contents does, both are returned. If you take away the contents of the folder, none are returned.
To be able to see every subfolder that contains a file use the parameters -file and -recurse of the Get-ChildItem cmdlet:
$a = $path0, $path1, $path2
foreach ($element in $a) { Get-ChildItem -Path $element\$date1 -file -Recurse | foreach {$_.Directory.Name} | select -uniq }
I would like to identify a specific empty folder in our user profiles.
I have a text file containing all of our user names that I want the script to refer to. The script will loop each user directory and either output to file or screen and say if the directory is empty. Hidden files do not have to count!
Something similar
FOR /F %U IN (C:\UserList\UserList.TXT) DO *Find and List Empty Folder* \\Server\Share\%U\Target_Folder
Powershell solutions welcome!
This article on Technet provides the following Powershell code snippet to identify all empty folders:
$a = Get-ChildItem C:\Scripts -recurse | Where-Object {$_.PSIsContainer -eq $True}
$a | Where-Object {$_.GetFiles().Count -eq 0} | Select-Object FullName
Replace "C:\Scripts" with the root folder you want to search.
Update:
The following script will get you in the ballpark.
$content = Get-Content C:\Temp\FolderList.txt
foreach ($line in $content)
{
Write-Host $line -NoNewline
$testObject = Test-Path -Path $line
if ($testObject)
{
$folder = Get-Item -Path $line
$filesCount = $folder.GetFiles().Count
if ($filesCount.Equals(0))
{
Write-Host " - Empty folder"
}
else
{
Write-Host " - Contains files"
}
}
else
{
Write-Host " - Invalid path"
}
}
I have this code :
$Count=0
Function DryRun-UploadFile($DestinationFolder, $File, $FileSource, $Count)
{
if($FileSource -eq $null){
$FileSource = $Folder
}
$path= [String]$FileSource+'\'+$File
$Size = get-item $Path
$Size = $Size.length
if($Size -lt 160000){
Write-Host "Passed"
}else{
$Count=$Count+1
}
}
function DryRun-PopulateFolder($ListRootFolder, $FolderRelativePath, $Count)
{
Write-Host "Uploading file " $file.Name "to" $WorkingFolder.name -ForegroundColor Cyan
if(!($File -like '*.txt')){
#Upload the file
DryRun-UploadFile $WorkingFolder $File $FileSource $Count
}else{
$Count=$Count+1
}
}
}
Function DryRun-Copy-Files{
$AllFolders = Get-ChildItem -Recurse -Path $Folder |? {$_.psIsContainer -eq $True}
#Get a list of all files that exist directly at the root of the folder supplied by the operator
$FilesInRoot = Get-ChildItem -Path $Folder | ? {$_.psIsContainer -eq $False}
#Upload all files in the root of the folder supplied by the operator
Foreach ($File in ($FilesInRoot))
{
#Notify the operator that the file is being uploaded to a specific location
Write-Host "Uploading file " $File.Name "to" $DocLibName -ForegroundColor Cyan
if(!($File -like '*.txt')){
#Upload the file
DryRun-UploadFile($list.RootFolder) $File $null $Count
}else{
$Count=$Count+1
}
}
#Loop through all folders (recursive) that exist within the folder supplied by the operator
foreach($CurrentFolder in $AllFolders)
{
DryRun-PopulateFolder ($list.RootFolder) $FolderRelativePath $Count
}
Write-output "Number of files excluded is: "$Count | Out-file DryRun.txt -append
}
I have removed some of my code for simplicity sake as it has nothing to do with my problem. My code goes through a file structure and counts up if the file is above 160000 bytes or is a txt file. run calling DryRun-Copy-Files.
And I have a variable called $count which I want to use in all the functions and then output what the count is to a file.
The problem is it only counts in the first function DryRun-Copy-Files not in the others
define the variable with global:
$global:count=0
and use it in the functions (don't explicit pass it)