I'm trying to write a script in PowerShell which reads in a "foreach" loop all the only files in a specific folder which contains "example" in it's name.
The problem is that I'm trying to save the content of each file in a variable without any success. Tried to use Get-Content $file and it throws the following error "Get-Content : Cannot find path" even though the path was set at the beginning to the Folder var and file actually contains the file that I need. I can't assign it to $FileContent
$Folder = Get-ChildItem U:\...\Source
foreach($file in $Folder)
{
if($file.Name -Match "example")
{
$FileContent = Get-Content $file
}
}
This happens as the FileInfo object's default behavior returns just the file's name. That is, there is no path information, so Get-Content tries to access the file from current directory.
Use FileInfo's FullName property to use absolute path. Like so,
foreach($file in $Folder)
{
...
$FileContent = Get-Content $file.FullName
Change your working directory to U:\...\Source and then it shall work.
Use
cd U:\...\Source
$folder = gci U:\...\Source
After you are done with your work, you can change your working directory again using cd command or the push-location cmdlet.
try this:
Get-ChildItem U:\...\Source -file -filter "*example*" | %{
$FileContent = Get-Content $_.fullname
}
Related
Alright, been working on this for hours and researching like crazy, but still not getting something to work. I need a string[] object created from get-childitem to pass to the Copy-Item -exclude parameter.
The hurdle is that I need to do recursion and need to have relative paths, so this is what I came up with:
$((Get-ChildItem -Path $Dest -Recurse -File).FullName.TrimStart($Dest))
This results in a clean list of existing files in $dest that are presented with a relative path to $dest. The problem is, if I add this to the copy-item -exclude parameter it seems to ignore it. Further research online suggests that copy-item will ignore the -exclude parameter if it is not of type string[].
If I check the type returned by the above command, I get System.Object[]. I expect it to be System.String[] or just plain String[].
How do I convert the output of the above command to a string array?
The full command using copy-item, for clarity, is:
Copy-Item -Path (Join-Path $src "*") -Destination $dest -Recurse -Force -Exclude $((Get-ChildItem -Path $Dest -Recurse -File).FullName.TrimStart($Dest))
My end goal is to copy files recursively without overwriting existing files.
To get a string[] from the names of get-childitem cmdlet use the following
[string[]]$files = (Get-ChildItem).Name
This will do what it appears you say that you want? But, I think that may not be everything to your question.
$((Get-ChildItem -Path $Dest -Recurse -File).FullName.Replace("$Dest",'.'))
#mklement0 is right, -Exclude and -Include support file name patterns (i.e. "*.txt") and not an array of explicit paths.
This sounds like an awful lot like an XY Problem ;-)
If you simply want to copy files recursively without overwriting them, use Robocopy with the Mirror switch. e.g.:
robocopy C:/Source C:/Dest /mir
EDIT:
By default Copy-Item will always overwrite the files on copy, and there is no switches to get around this. I usually recommend Robocopy as it really simplifies things like this and is very "robust" and reliable.
If your requirements are for a "pure" PowerShell version, then you have to break the scrip out into two parts, 1. Get a list of all the files 2. Iterate through the filer and test to see if they are already in the destination before copying.
$SrcPath = "C:/Source"
$DestPath = "C:/Dest"
$SrcFiles = Get-ChildItem $SrcPath -Recurse
#Iterate through files testing:
$SrcFiles | ForEach-Object {
#Calculate Destination File/Folder name/path
$DestObj = $_.FullName.Replace($SrcPath, $DestPath)
if(Test-Path -LiteralPath $DestObj)
{
#File already Exists
Write-Host "File already Exists: $DestObj"
}
else
{
#File Does not exist - Copy
Write-Host "File Does not Exist Copy: $DestObj"
Copy-Item -Path $_ -Destination $DestObj
}
}
This question already has answers here:
How to properly -filter multiple strings in a PowerShell copy script
(5 answers)
Closed 6 years ago.
I have this script and it's working 100% , but only for a single item
I want to loop the script and get content from a txt file
You see, my scipt search for a specific file and copy it to an existing folder with the same name of the file.
So what I want is to get the folder's name and the file's name from 2 txt files and loop the script
I have manage to get the content from the txt files but I can't loop the script if I add a second line with new values in my txt files.
I always get the error:
Get-ChildItem : Cannot convert 'System.Object[]' to the type
'System.String' required by parameter 'Filter'. Specified method is
not supporte d.
Ok this is my script:
Set-ExecutionPolicy -Scope Process -ExecutionPolicy RemoteSigned
# Setup source and destination paths
$Src = '\\192.168.0.216\home\'
$Dst = 'C:\TEST\120629B\'
# Wildcard for filter
$Extension = '120629B.jpg'
# Get file objects recursively
Get-ChildItem -Path $Src -Filter $Extension -Recurse |
# Skip directories, because XXXReadMe.txt is a valid directory name
Where-Object {!$_.PsIsContainer} |
# For each file
ForEach-Object {
# If file exist in destination folder, rename it with directory tag
if(Test-Path -Path (Join-Path -Path $Dst -ChildPath $_.Name))
{
# Get full path to the file without drive letter and replace `\` with '-'
# [regex]::Escape is needed because -replace uses regex, so we should escape '\'
$NameWithDirTag = (Split-Path -Path $_.FullName -NoQualifier) -replace [regex]::Escape('\'), '-'
# Join new file name with destination directory
$NewPath = Join-Path -Path $Dst -ChildPath $NameWithDirTag
}
# Don't modify new file path, if file doesn't exist in target dir
else
{
$NewPath = $Dst
}
# Copy file
Copy-Item -Path $_.FullName -Destination $NewPath
}
Ok this is what I have change and worked but is only working with one record
$Src = '\\192.168.0.216\home\'
$Dst = Get-Content 'C:\TEST\path.txt'
# Wildcard for filter
$Extension = Get-Content 'C:\TEST\file.txt'
The error message is telling you the problem, you can't use an array as the filter for get-childitem. you can probably nest a where-object filter inside of a foreach loop but the easiest way to accomplish what you are trying to do is going to be to loop through your extension filters and then run your loop inside of that loop. so wrap your entire Get-ChildItem loop in a Foreach loop as below.
Foreach($e in $extension){
*Your Code Here*
}
Of cource make sure to change the -Filter parameter of your Get-ChildItem from $Extension to $e
Like error says, -Filter expects a single string. Get-Content would be returning an object array for files with more than one line.
Since you are also using -Recurse consider using -Include instead of -Filter since it supports arrays of stings. This should without changing your input file or adding any other post processing. From [MSDN]
Specifies, as a string array, an item or items that this cmdlet includes in the operation. The value of this parameter qualifies the Path parameter. Enter a path element or pattern, such as *.txt. Wildcards are permitted.
Get-ChildItem -Path $Src -Include $Extension -Recurse
Note:
The Include parameter is effective only when the command includes the Recurse parameter or the path leads to the contents of a directory, such as C:\Windows*, where the wildcard character specifies the contents of the C:\Windows directory.
Same goes for -Exclude as well
$folder = filestructure
# Get a recursive list of all folders beneath the folder supplied by the operator
$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}
Foreach ($File in ($FilesInRoot))
{
#Notify the operator that the file is being uploaded to a specific location
if($Global:successfullymigrated -contains $File){
Write-Host $File
}
}
###this part doesn't work
foreach($CurrentFolder in $AllFolders)
{
# Set the FolderRelativePath by removing the path of the folder supplied
# by the operator from the fullname of the folder
$FolderRelativePath = ($CurrentFolder.FullName).Substring($Folder.Length)
$FileSource = $Folder + $FolderRelativePath
$FilesInFolder = Get-ChildItem -Path $FileSource | ? {$_.psIsContainer -eq $False}
# For each file in the source folder being evaluated, call the UploadFile
# function to upload the file to the appropriate location
Foreach ($File in ($FilesInFolder))
{
Write-Host $File
if($Global:successfullymigrated -contains $File){
Write-Host $File
}
}
}
My code above is supposed to go through a file structure and checks to see if any of the file names are in the array (which is an array of strings with file names in them). My code works for the root files, prints out all the files that are in the array but when we get to checking the files in the other folders beyond the root it doesn't work. Even though it outputs the files that are in the file structure. I am completely stuck.
Forgive me if I have misunderstood but I read this
My code above is supposed to go through a file structure and checks to see if any of the file names are in the array
And interpreted that as you are just looking for file paths for files that match exactly a list of names you provide.
So I have this sample which should do just that.
$Global:successfullymigrated = #("template.txt","winmail.dat")
$folder = "C:\temp"
Get-ChildItem $folder -recurse | Where-Object{$Global:successfullymigrated -contains $_.Name -and !$_.psIsContainer} | Select-Object -ExpandProperty FullName
You should be able to incorporate this into your own code. It outputs the full paths to the matching files. The example I have outputs file from root and substructure.
C:\temp\winmail.dat
C:\temp\docs\template.txt
!$_.psIsContainer is to ensure that we do not get folders returned in our results. If you have PowerShell 3.0 or above then that can be replaced by the -File switch of Get-ChildItem
I have looked for questions relating to my issue, but can't find the correct syntax to use for what I want to achieve.
I want to take all the filenames from a folder using Get-ChildItem, and store these in a variable, then rename all the files in another folder using these names.
From what I have seen, I need something similar to:
CD directory a
$newnames = Get-ChildItem
CD directory b
Get-ChildItem | Foreach {$name = $newnames} | Rename-Item -Newname {$name}
I think perhaps the issue I am facing, is calling the name correctly from the $newnames variable.
Can anyone advise the correct syntax for what I need to do?
Here's one way assuming you have the same count of files in those folders. Remove the -WhatIf switch to actually rename the files:
[array]$a = Get-ChildItem .\DirA
[array]$b = Get-ChildItem .\DirB
for($i=0; $i -lt $a.Length; $i++)
{
$b[$i] | Rename-Item -NewName $a[$i] -WhatIf
}
So I have folder with files in it, in a certain location
C:\Users\ainfowara\Desktop\testfiles
so I want to move those files to this location
C:\Users\ainfowara\Desktop\destinationTestfiles
the "testfiles" have files of this format txt.*.test.* so basically I wanna check before I move the files that they have those two main stuff (txt) and (test) in the third part.
can someone help me, how can perform this in powershell script
I know I can do this, to set the folders paths
path_src= C:\Users\ainfowara\Desktop\testfiles
path_dst= C:\Users\ainfowara\Desktop\destinationTestfiles
thanks in advance for the help
If there are no subfolders in testfiles(at least that you need files from), try this:
$src = "C:\Users\ainfowara\Desktop\testfiles"
$dst = "C:\Users\ainfowara\Desktop\destinationTestfiles"
Get-ChildItem $src -Filter "txt.*.test.*" | Move-Item -Destination $dst -Force
If you have files in subfolders of the source-path, try this:
$src = "C:\Users\ainfowara\Desktop\testfiles"
$dst = "C:\Users\ainfowara\Desktop\destinationTestfiles"
Get-ChildItem $src -Filter "txt.*.test.*" -Recurse | % {
#Creates an empty file at the destination to make sure that subfolders exists
New-Item -Path $_.FullName.Replace($src,$dst) -ItemType File -Force
Move-Item -Path $_.FullName -Destination $_.FullName.Replace($src,$dst) -Force
}
Be aware that if your filename contains square-bracket [ ] you need another script (known PS bug).