I am reformatting some JSON files, moving them to a new folder, and then searching them for some text. This script worked perfectly for a separate folder of JSON files. All I did was change the folder name, and now it can't find SOME of the files. I can't find anything different about these ones. Help!
$targetfolder = "C:\Users\jutrust\documents\MyFolder\*.json"
$files= get-childitem -path ($TargetFolder -replace '^"|"$') -recurse
foreach($file in $files)
{
$content = Get-Content $file -Raw | ConvertFrom-Json
$newFilePath = $file.FullName.Replace("MyFolder","MyNewFolder")
ConvertTo-Json -InputObject $content -depth 100| Set-Content $newFilePath
$filename = [System.IO.Path]::GetFileNameWithoutExtension($newFilePath)
$Line = Select-String -AllMatches -Path $Newfilepath -pattern "mytext"
Error looks like:
get-childitem : Could not find item C:\Users\jutrust\documents\MyFolder\File1_ name with (these
characters)_fg45f-fjh546-rt4de8-4rsgt7489.json.
$files= get-childitem -path ($TargetFolder -replace '^"|"$') -Recurse
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
CategoryInfo : ObjectNotFound: (C:\Users\jutrust...7489.json:String) [Get-ChildItem], IOException
FullyQualifiedErrorId : ItemNotFound,Microsoft.PowerShell.Commands.GetChildItemCommand
Edit for more info: That error is only for the first one for some reason. Every other error says:
Select-String : Cannot find path 'C:\Users\jutrust\documents\MyNewFolder\File2_ name with (different characters)_htg86ffgh6-gh8674-trh897rt.json' because it does not exist.
Which means it's not moving those files to the new folder. If I put one of the erring files as the $targetfolder directly, I get the more specific:
get-childitem : Illegal characters in path.
It is the direct, copied path. It exists with that name. Why would there be an issue?
CodePudding user response:
Try using full file name, like below. Also better use string replace inside for loop
$targetfolder = "C:\Users\jutrust\documents\MyFolder"
$files= (Get-ChildItem "$targetfolder\*.json" -Recurse).FullName
foreach($file in $files)
{
$file=$file.Replace('^"|"$','')
$content = Get-Content $file -Raw | ConvertFrom-Json
$newFilePath = $file.FullName.Replace("MyFolder","MyNewFolder")
ConvertTo-Json -InputObject $content -depth 100| Set-Content $newFilePath
$filename = [System.IO.Path]::GetFileNameWithoutExtension($newFilePath)
$Line = Select-String -AllMatches -Path $Newfilepath -pattern "mytext"
}
CodePudding user response:
Although it is not clear to me why you would want to convert a json file to object in $content
and then re-convert that object back to json
without manipulating the data while you have it as object, the error message shows you have characters in the file name (most likely square brackets)
for which you need to use -LiteralPath
instead of -Path
.
Your code could be improved like below:
$sourceFolder = 'C:\Users\jutrust\documents\MyFolder'
$targetFolder = 'C:\Users\jutrust\documents\MyNewFolder'
$files = Get-ChildItem -LiteralPath $sourceFolder -Filter '*.json' -File -Recurse
foreach ($file in $files) {
$content = Get-Content -LiteralPath $file.FullName -Raw | ConvertFrom-Json
# calculate the new destination path and create that subfolder if it doesn't already exist
$destination = Join-Path -Path $targetFolder -ChildPath $file.DirectoryName.Substring($SourceFolder.Length)
$null = New-Item -Path $destination -ItemType Directory -Force
# construct the full destination by combining the target path with the actual filename
$newFile = Join-Path -Path $destination -ChildPath $file.Name
$content | ConvertTo-Json -Depth 100 | Set-Content -LiteralPath $newFile
# now do whatever you need to do with that new file
$Line = Select-String -AllMatches -LiteralPath $newFile -Pattern "mytext"
# ...
}
Notes:
Join-Path
does not have a-LiteralPath
parameter because it is purely a cmdlet that operates on strings without trying to resolve wildcard characters- Using
.Replace()
on the path to obtain the destination path is tricky; better use Join-Path and the file'sDirectoryName
for that - Always check/create the destination folder before you try to create or copy a file to that path
- Append switch
-File
on the Get-ChildItem cmdlet so it doesn't also return DirectoryInfo objects as well - With filesystem paths, using the
New-Item
cmdlet with switch-Force
either creates the folder or returns a reference object of an existing folder. Than means you do not have to explicitely test if the folder exists or not. Warning though. DO NOT use that technique on paths other than FileSystem paths (like for instance registry paths) because there you may risk losing all content of the existing container.