{"id":7921,"date":"2020-12-02T16:46:00","date_gmt":"2020-12-02T21:46:00","guid":{"rendered":"https:\/\/jdhitsolutions.com\/blog\/?p=7921"},"modified":"2020-12-02T16:46:05","modified_gmt":"2020-12-02T21:46:05","slug":"answering-the-powershell-linking-challenge","status":"publish","type":"post","link":"https:\/\/jdhitsolutions.com\/blog\/powershell\/7921\/answering-the-powershell-linking-challenge\/","title":{"rendered":"Answering the PowerShell Linking Challenge"},"content":{"rendered":"\n<p>A few weeks ago, the <a href=\"https:\/\/ironscripter.us\/a-powershell-linking-challenge\/\" target=\"_blank\" rel=\"noreferrer noopener\">Iron Scripter challenge<\/a> was to move files meeting some criteria to a new location and leave a link behind. As I've written before, these challenges are a great way to test your PowerShell skills and stretch yourself. This challenge has a number of moving parts. <\/p>\n\n\n\n<p>Often with PowerShell some of the hardest work is planning and organization. How are you going to achieve a given task? If you are writing code that someone else will be using, what expectations or assumptions will they have? How are they likely to use your commands? I also think about flexibility and re-use. I try to avoid writing a monolithic function that does several things. Rather, you should focus on small, single-use tasks that you can combine in a pipelined expression. Or orchestrate from a controller script, which is what I will be showing you later.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\">Testing the Core Command<\/h2>\n\n\n\n<p>The core command in this task is New-Item. You can use this cmdlet to create files, folders and links. I'm assuming you will look at full help and examples. I'll give it a spin.<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code lang=\"powershell\" class=\"language-powershell\">New-Item -ItemType SymbolicLink -Path . -Name procmon.exe -Value D:\\OneDrive\\tools\\Procmon.exe<\/code><\/pre>\n\n\n\n<p>This command will create a link to D:\\OneDrive\\tools\\Procmon.exe in the current directory.<\/p>\n\n\n\n<figure class=\"wp-block-image size-large is-style-default\"><img loading=\"lazy\" decoding=\"async\" width=\"1024\" height=\"163\" src=\"https:\/\/jdhitsolutions.com\/blog\/wp-content\/uploads\/2020\/12\/new-item-link-1024x163.png\" alt=\"\" class=\"wp-image-7922\" srcset=\"https:\/\/jdhitsolutions.com\/blog\/wp-content\/uploads\/2020\/12\/new-item-link-1024x163.png 1024w, https:\/\/jdhitsolutions.com\/blog\/wp-content\/uploads\/2020\/12\/new-item-link-300x48.png 300w, https:\/\/jdhitsolutions.com\/blog\/wp-content\/uploads\/2020\/12\/new-item-link-768x122.png 768w, https:\/\/jdhitsolutions.com\/blog\/wp-content\/uploads\/2020\/12\/new-item-link-1536x244.png 1536w, https:\/\/jdhitsolutions.com\/blog\/wp-content\/uploads\/2020\/12\/new-item-link-850x135.png 850w, https:\/\/jdhitsolutions.com\/blog\/wp-content\/uploads\/2020\/12\/new-item-link.png 1888w\" sizes=\"auto, (max-width: 1024px) 100vw, 1024px\" \/><\/figure>\n\n\n\n<p>I can run procmon.exe in C:\\Work without caring where the actual file resides. Excellent. The premise of the challenge is to go through a list of files, move them to a destination and leave a link behind. <\/p>\n\n\n\n<h2 class=\"wp-block-heading\">Move and Link<\/h2>\n\n\n\n<p>This sounds like a task I might want to re-use. I don't want to limit what files to process. I want to be able to pass any file to my command and have it move and link. Technically, PowerShell has a Move-Item command, but I'm thinking of the \"move and link\" process as a single action so I will code it that way. Plus, there are a few other challenge features I want to address.<\/p>\n\n\n\n<p>Here's my function for \"move and link\".<\/p>\n\n\n\n<pre class=\"wp-block-code\" title=\"Move-FileLink.ps1\"><code lang=\"powershell\" class=\"language-powershell\">#requires -version 5.1\nFunction Move-FileWithLink {\n    [CmdletBinding(SupportsShouldProcess)]\n    Param(\n        [Parameter(Position = 0, Mandatory, HelpMessage = \"Specify the path of a file to move.\", ValueFromPipelineByPropertyName)]\n        [alias(\"fullname\")]\n        [ValidateNotNullOrEmpty()]\n        [ValidateScript({ Test-Path $_ })]\n        [string]$Path,\n\n        [Parameter(HelpMessage = \"Specify the top-level target path. It will be created if it doesn't exist.\")]\n        [ValidateNotNullOrEmpty()]\n        [string]$Destination = \"\\\\172.16.10.100\\backup\\lts\",\n\n        [switch]$Passthru\n    )\n    Begin {\n        Write-Verbose \"[$((Get-Date).TimeofDay) BEGIN  ] Starting $($myinvocation.mycommand)\"\n        #define a timestamped logfile\n        $logname = \"{0}_MoveLink.log\" -f (Get-Date -Format \"yyyy_MM-dd-hhmm\")\n        #using .NET to support cross-platform\n        $logfile = Join-Path -Path $([System.io.path]::GetTemppath()) -ChildPath $logname\n        Write-Verbose \"[$((Get-Date).TimeofDay) BEGIN  ] Logging activity to $logfile\"\n\n        #define a logging helper function\n        function log {\n            [cmdletbinding(SupportsShouldProcess)]\n            param([string]$Message, [string]$LogFile)\n            $text = \"[{0}] {1}\" -f (Get-Date -Format u), $Message\n            $text | Out-File -FilePath $logFile -Force -Append\n        }\n\n        #set the default parameter value for the log function\n        $PSDefaultParameterValues[\"log:logfile\"] = $logfile\n\n        log \"Starting: $($myinvocation.MyCommand)\"\n        $who = \"$([System.Environment]::UserDomainName)\\$([System.Environment]::UserName)\"\n        $where = [System.Environment]::MachineName\n        log \"User: $who\"\n        log \"Computer: $where\"\n\n        if (-Not (Test-Path -Path $Destination)) {\n            Try {\n                log \"Creating $destination\"\n                [void](New-Item -ItemType Directory -Path $Destination -Force -ErrorAction Stop)\n            }\n            Catch {\n                Throw $_\n            }\n        }\n    } #begin\n    Process {\n        $Path = Convert-Path $path\n        Write-Verbose \"[$((Get-Date).TimeofDay) PROCESS] Processing $Path\"\n        log \"Processing $path\"\n        $parent = Split-Path -Path $path\n        $name = Split-Path -Path $path -Leaf\n        #get the relative path so it can be reconstructed in the destination\n        $target = Join-Path -Path $Destination -ChildPath $parent.Substring(3)\n\n        if ($pscmdlet.ShouldProcess($path, \"Move file to $target\")) {\n            Try {\n                #recreate file structure\n                if (-Not (Test-Path -Path $Target)) {\n                    Write-Verbose \"[$((Get-Date).TimeofDay) PROCESS] Creating $Target\"\n                    [void](New-Item -ItemType Directory -Path $Target -Force -ErrorAction Stop)\n                    log \"Created target $target\"\n                }\n                Write-Verbose \"[$((Get-Date).TimeofDay) PROCESS] Moving file to $Target\"\n                $m = Move-Item -Path $path -Destination $target -PassThru -ErrorAction Stop\n                log \"Moved $path to $target\"\n            }\n            Catch {\n                $msg = \"Failed to move $path to $target. $($_.Exception.message)\"\n                Write-Warning $msg\n                log $msg\n            }\n        }\n\n        Write-Verbose \"[$((Get-Date).TimeofDay) PROCESS] Creating link for $path\"\n        if ($pscmdlet.ShouldProcess($path, \"Creating link\")) {\n            if (Test-Path $m.fullname) {\n                Try {\n                    $link = New-Item -ItemType SymbolicLink -Name $name -Path $parent -Value $m.FullName -Force -ErrorAction Stop\n                    log \"Created symboliclink from $($m.fullname)\"\n                    if ($passthru) {\n                        $link\n                    }\n                }\n                Catch {\n                    $msg = \"Failed to create link to $path from $($m.fullname). $($_.Exception.message)\"\n                    Write-Warning $msg\n                    log $msg\n                }\n            }\n        }\n\n    } #process\n    End {\n        log \"Ending: $($myinvocation.MyCommand)\"\n        if (Test-Path $logfile) {\n            Write-Verbose \"[$((Get-Date).TimeofDay) END    ] Activity logged at $logfile\"\n        }\n        if ($PSDefaultParameterValues.ContainsKey(\"log:logfile\")) {\n            $PSDefaultParameterValues.Remove(\"log:logfile\")\n        }\n        Write-Verbose \"[$((Get-Date).TimeofDay) END    ] Ending $($myinvocation.mycommand)\"\n    } #end\n}<\/code><\/pre>\n\n\n\n<p>The function will take a filename as a parameter, copy it to the destination, then create a link in the original location. The function has a hard-coded logging function that will create a text-based log file in the user's %TEMP% folder.<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code lang=\"powershell\" class=\"language-powershell\">$logname = \"{0}_MoveLink.log\" -f (Get-Date -Format \"yyyy_MM-dd-hhmm\")\n#using .NET to support cross-platform\n$logfile = Join-Path -Path $([System.io.path]::GetTemppath()) -ChildPath $logname\n\nfunction log {\n    [cmdletbinding(SupportsShouldProcess)]\n    param([string]$Message, [string]$LogFile)\n    $text = \"[{0}] {1}\" -f (Get-Date -Format u), $Message\n    $text | Out-File -FilePath $logFile -Force -Append\n}<\/code><\/pre>\n\n\n\n<p>I wrote a short helper function so that each log entry will include a UTC time stamp. I wanted to keep my code simple, so I temporarily set a PSDefaultParameterValue for the function.<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code lang=\"powershell\" class=\"language-powershell\">#set the default parameter value for the log function\n$PSDefaultParameterValues[\"log:logfile\"] = $logfile\n\nlog \"Starting: $($myinvocation.MyCommand)\"<\/code><\/pre>\n\n\n\n<p>This makes it easy to log events throughout the script. At the end of the function, I remove the PSDefaultParameterValue.<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code lang=\"powershell\" class=\"language-powershell\">if ($PSDefaultParameterValues.ContainsKey(\"log:logfile\")) {\n    $PSDefaultParameterValues.Remove(\"log:logfile\")\n}<\/code><\/pre>\n\n\n\n<p>The function uses the cmdletbinding attribute to enable -WhatIf. Even though most of the commands I'm using will automatically detect -WhatIf, I opted to create my own -WhatIf code to have a bit more control over the messaging.<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code lang=\"powershell\" class=\"language-powershell\">if ($pscmdlet.ShouldProcess($path, \"Move file to $target\")) {\n    Try {\n        #recreate file structure\n        if (-Not (Test-Path -Path $Target)) {\n            Write-Verbose \"[$((Get-Date).TimeofDay) PROCESS] Creating $Target\"\n            [void](New-Item -ItemType Directory -Path $Target -Force -ErrorAction Stop)\n            log \"Created target $target\"\n        }\n        Write-Verbose \"[$((Get-Date).TimeofDay) PROCESS] Moving file to $Target\"\n        $m = Move-Item -Path $path -Destination $target -PassThru -ErrorAction Stop\n        log \"Moved $path to $target\"\n    }\n    Catch {\n        $msg = \"Failed to move $path to $target. $($_.Exception.message)\"\n        Write-Warning $msg\n        log $msg\n    }\n}<\/code><\/pre>\n\n\n\n<p>I can use the function like this:<\/p>\n\n\n\n<figure class=\"wp-block-image size-large is-style-default\"><img loading=\"lazy\" decoding=\"async\" width=\"1024\" height=\"336\" src=\"https:\/\/jdhitsolutions.com\/blog\/wp-content\/uploads\/2020\/12\/move-link-whatif-1024x336.png\" alt=\"\" class=\"wp-image-7923\" srcset=\"https:\/\/jdhitsolutions.com\/blog\/wp-content\/uploads\/2020\/12\/move-link-whatif-1024x336.png 1024w, https:\/\/jdhitsolutions.com\/blog\/wp-content\/uploads\/2020\/12\/move-link-whatif-300x99.png 300w, https:\/\/jdhitsolutions.com\/blog\/wp-content\/uploads\/2020\/12\/move-link-whatif-768x252.png 768w, https:\/\/jdhitsolutions.com\/blog\/wp-content\/uploads\/2020\/12\/move-link-whatif-1536x505.png 1536w, https:\/\/jdhitsolutions.com\/blog\/wp-content\/uploads\/2020\/12\/move-link-whatif-850x279.png 850w\" sizes=\"auto, (max-width: 1024px) 100vw, 1024px\" \/><\/figure>\n\n\n\n<p>The WhatIf is also detected for the logging function. I'll move and link the file.<\/p>\n\n\n\n<figure class=\"wp-block-image size-large is-style-default\"><img loading=\"lazy\" decoding=\"async\" width=\"1024\" height=\"269\" src=\"https:\/\/jdhitsolutions.com\/blog\/wp-content\/uploads\/2020\/12\/move-link-poc-1024x269.png\" alt=\"\" class=\"wp-image-7924\" srcset=\"https:\/\/jdhitsolutions.com\/blog\/wp-content\/uploads\/2020\/12\/move-link-poc-1024x269.png 1024w, https:\/\/jdhitsolutions.com\/blog\/wp-content\/uploads\/2020\/12\/move-link-poc-300x79.png 300w, https:\/\/jdhitsolutions.com\/blog\/wp-content\/uploads\/2020\/12\/move-link-poc-768x202.png 768w, https:\/\/jdhitsolutions.com\/blog\/wp-content\/uploads\/2020\/12\/move-link-poc-1536x404.png 1536w, https:\/\/jdhitsolutions.com\/blog\/wp-content\/uploads\/2020\/12\/move-link-poc-850x223.png 850w, https:\/\/jdhitsolutions.com\/blog\/wp-content\/uploads\/2020\/12\/move-link-poc.png 2043w\" sizes=\"auto, (max-width: 1024px) 100vw, 1024px\" \/><\/figure>\n\n\n\n<p>And here's what ends up in my log.<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code lang=\"bash\" class=\"language-bash\">[2020-12-02 16:16:37Z] Starting: Move-FileWithLink\n[2020-12-02 16:16:37Z] User: PROSPERO\\Jeff\n[2020-12-02 16:16:37Z] Computer: PROSPERO\n[2020-12-02 16:16:37Z] Creating d:\\archive\n[2020-12-02 16:16:37Z] Processing C:\\work\\s.clixml\n[2020-12-02 16:16:37Z] Created target d:\\archive\\work\n[2020-12-02 16:16:37Z] Moved C:\\work\\s.clixml to d:\\archive\\work\n[2020-12-02 16:16:37Z] Created symboliclink from D:\\archive\\work\\s.clixml\n[2020-12-02 16:16:37Z] Ending: Move-FileWithLink<\/code><\/pre>\n\n\n\n<h2 class=\"wp-block-heading\">Using a Controller Script<\/h2>\n\n\n\n<p>Now that I have a working tool to move and link files I need an easy way to use it. This is where considering <em>who <\/em>will be using your command and <em>how<\/em>, comes into play. The move and link function will take any input. An experienced PowerShell user could simply run a command like this:<\/p>\n\n\n\n<figure class=\"wp-block-image size-large is-style-default\"><img loading=\"lazy\" decoding=\"async\" width=\"1024\" height=\"304\" src=\"https:\/\/jdhitsolutions.com\/blog\/wp-content\/uploads\/2020\/12\/control-a-1024x304.png\" alt=\"\" class=\"wp-image-7926\" srcset=\"https:\/\/jdhitsolutions.com\/blog\/wp-content\/uploads\/2020\/12\/control-a-1024x304.png 1024w, https:\/\/jdhitsolutions.com\/blog\/wp-content\/uploads\/2020\/12\/control-a-300x89.png 300w, https:\/\/jdhitsolutions.com\/blog\/wp-content\/uploads\/2020\/12\/control-a-768x228.png 768w, https:\/\/jdhitsolutions.com\/blog\/wp-content\/uploads\/2020\/12\/control-a-1536x456.png 1536w, https:\/\/jdhitsolutions.com\/blog\/wp-content\/uploads\/2020\/12\/control-a-850x252.png 850w\" sizes=\"auto, (max-width: 1024px) 100vw, 1024px\" \/><\/figure>\n\n\n\n<p>But, the challenge was looking for a tool a user could run where they could specify locations. The challenge was also looking for a tool to move and link files last modified before a given date. I wrote a<em> controller script<\/em>.<\/p>\n\n\n\n<p>This type of script is designed to wrap-around a few core commands and execute them in a structured manner. You could run the commands in the script manually and achieve the same result. Controller scripts can also use parameters and almost any scripting feature you would have in a function.<\/p>\n\n\n\n<pre class=\"wp-block-code\" title=\"Archive-Folder.ps1\"><code lang=\"powershell\" class=\"language-powershell\">#requires -version 5.1\n\n&lt;#\nmove specified files to an alternate location, leaving\nlinked copies behind\n\nSpecify the source folder\nSpecify the target folder\nSpecify the last modified age\nSupport recursion\nSupport an exclude filter\n\nThis could be turned into a function instead of a control script\n#>\n\n[CmdletBinding(SupportsShouldProcess)]\nParam (\n    [parameter(Position = 0, Mandatory, HelpMessage = \"The folder to process for old files.\", ValueFromPipeline)]\n    [ValidateScript({Test-Path $_ })]\n    [string]$Path,\n    [parameter(Position = 1, Mandatory, HelpMessage = \"The top-level destination folder.\")]\n    [string]$Destination,\n    [Parameter(HelpMessage = \"Specify the last modified cutoff date.\")]\n    [datetime]$LastModified = (Get-Date).AddDays(-180).Date,\n    [parameter(HelpMessage = \"Recurse for files from the given path.\")]\n    [switch]$Recurse,\n    [parameter(HelpMessage = \"Specify a file pattern to exclude. Wildcards are permitted.\")]\n    [string]$Exclude,\n    [switch]$Passthru\n)\n\nBegin {\n    Write-Verbose \"[$((Get-Date).TimeofDay) BEGIN  ] Starting $($myinvocation.mycommand)\"\n\n    #dot source the function that moves files and creates links\n    . $PSScriptRoot\\Move-FileLink.ps1\n\n    $getParams = @{\n        ErrorAction = \"Stop\"\n        File = $True\n    }\n    if ($Recurse) {\n        $getParams.Add(\"Recurse\",$True)\n    }\n    $moveParams = @{\n        Destination = $Destination\n        Passthru = $Passthru\n    }\n    Write-Verbose \"[$((Get-Date).TimeofDay) BEGIN  ] Finding files last modified before $LastModified\"\n    if ($Exclude) {\n        Write-Verbose \"[$((Get-Date).TimeofDay) BEGIN  ] Excluding files that match the pattern $Exclude\"\n    }\n    Write-Verbose \"[$((Get-Date).TimeofDay) BEGIN  ] Using a destination of $destination\"\n\n} #begin\n\nProcess {\n    #convert to a complete file-system path\n    $Path = Convert-Path $Path\n    Write-Verbose \"[$((Get-Date).TimeofDay) PROCESS] Processing $Path\"\n    $getParams.Path = $Path\n\n    #build a filter for Where-Object. -Exclude only works with Get-Childitem when using\n    #recurse, which the user might not want.\n    if ($Exclude) {\n        Get-ChildItem @getParams | Where-object {($_.LastWriteTime -lt $LastModified) -AND ($_.name -notlike $Exclude)} |\n        Move-FileWithLink @moveParams\n    }\n    else {\n        Get-ChildItem @getParams | Where-Object { $_.LastWriteTime -lt $LastModified } | Move-FileWithLink @moveParams\n    }\n} #process\n\nEnd {\n    Write-Verbose \"[$((Get-Date).TimeofDay) END    ] Ending $($myinvocation.mycommand)\"\n} #end<\/code><\/pre>\n\n\n\n<p>It wouldn't take much to convert this into a function if I wanted to. In fact, I often start with stand-alone scripts because I can run them without the extra step of dot-sourcing. Once I'm happy with the code, adding the function bits is trivial.<\/p>\n\n\n\n<p>Let's see this script in action.<\/p>\n\n\n\n<figure class=\"wp-block-image size-large is-style-default\"><img loading=\"lazy\" decoding=\"async\" width=\"1024\" height=\"490\" src=\"https:\/\/jdhitsolutions.com\/blog\/wp-content\/uploads\/2020\/12\/control-whatif-1024x490.png\" alt=\"\" class=\"wp-image-7927\" srcset=\"https:\/\/jdhitsolutions.com\/blog\/wp-content\/uploads\/2020\/12\/control-whatif-1024x490.png 1024w, https:\/\/jdhitsolutions.com\/blog\/wp-content\/uploads\/2020\/12\/control-whatif-300x143.png 300w, https:\/\/jdhitsolutions.com\/blog\/wp-content\/uploads\/2020\/12\/control-whatif-768x367.png 768w, https:\/\/jdhitsolutions.com\/blog\/wp-content\/uploads\/2020\/12\/control-whatif-1536x734.png 1536w, https:\/\/jdhitsolutions.com\/blog\/wp-content\/uploads\/2020\/12\/control-whatif-850x406.png 850w, https:\/\/jdhitsolutions.com\/blog\/wp-content\/uploads\/2020\/12\/control-whatif.png 2035w\" sizes=\"auto, (max-width: 1024px) 100vw, 1024px\" \/><\/figure>\n\n\n\n<p>The Verbose output makes it clear what the command is going to do.<\/p>\n\n\n\n<figure class=\"wp-block-image size-large is-style-default\"><img loading=\"lazy\" decoding=\"async\" width=\"1024\" height=\"339\" src=\"https:\/\/jdhitsolutions.com\/blog\/wp-content\/uploads\/2020\/12\/control-move-1024x339.png\" alt=\"\" class=\"wp-image-7928\" srcset=\"https:\/\/jdhitsolutions.com\/blog\/wp-content\/uploads\/2020\/12\/control-move-1024x339.png 1024w, https:\/\/jdhitsolutions.com\/blog\/wp-content\/uploads\/2020\/12\/control-move-300x99.png 300w, https:\/\/jdhitsolutions.com\/blog\/wp-content\/uploads\/2020\/12\/control-move-768x254.png 768w, https:\/\/jdhitsolutions.com\/blog\/wp-content\/uploads\/2020\/12\/control-move-1536x508.png 1536w, https:\/\/jdhitsolutions.com\/blog\/wp-content\/uploads\/2020\/12\/control-move-850x281.png 850w, https:\/\/jdhitsolutions.com\/blog\/wp-content\/uploads\/2020\/12\/control-move.png 1989w\" sizes=\"auto, (max-width: 1024px) 100vw, 1024px\" \/><\/figure>\n\n\n\n<h2 class=\"wp-block-heading\">Summary<\/h2>\n\n\n\n<p>The core command is flexible and re-usable beyond the challenge requirements. The rest of the challenge requirements are met in the control script. I think many people overlook this concept. Not everything has to be put into a function. A control script is a great way of ensuring consistency. You can sign these scripts, check them into source control, and manage them the same way you handle your PowerShell modules.<\/p>\n\n\n\n<p>If you feel you need to improve your PowerShell scripting skills, consider grabbing a copy of  <a href=\"https:\/\/leanpub.com\/powershell-scripting-toolmaking\/\" target=\"_blank\" rel=\"noreferrer noopener nofollow\">The PowerShell Scripting and Toolmaking Book.<\/a><\/p>\n","protected":false},"excerpt":{"rendered":"<p>A few weeks ago, the Iron Scripter challenge was to move files meeting some criteria to a new location and leave a link behind. As I&#8217;ve written before, these challenges are a great way to test your PowerShell skills and stretch yourself. This challenge has a number of moving parts. Often with PowerShell some of&#8230;<\/p>\n","protected":false},"author":1,"featured_media":0,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"_monsterinsights_skip_tracking":false,"_monsterinsights_sitenote_active":false,"_monsterinsights_sitenote_note":"","_monsterinsights_sitenote_category":0,"_jetpack_memberships_contains_paid_content":false,"footnotes":"","jetpack_publicize_message":"New on the blog: Answering the #PowerShell Linking Challenge","jetpack_publicize_feature_enabled":true,"jetpack_social_post_already_shared":true,"jetpack_social_options":{"image_generator_settings":{"template":"highway","default_image_id":0,"font":"","enabled":false},"version":2}},"categories":[4],"tags":[],"class_list":["post-7921","post","type-post","status-publish","format-standard","hentry","category-powershell"],"yoast_head":"<!-- This site is optimized with the Yoast SEO plugin v27.4 - https:\/\/yoast.com\/product\/yoast-seo-wordpress\/ -->\n<title>Answering the PowerShell Linking Challenge &#8226; The Lonely Administrator<\/title>\n<meta name=\"description\" content=\"My commentary and code on a recent Iron Scripter PowerShell challenge to move and link old files using symbolic links.\" \/>\n<meta name=\"robots\" content=\"index, follow, max-snippet:-1, max-image-preview:large, max-video-preview:-1\" \/>\n<link rel=\"canonical\" href=\"https:\/\/jdhitsolutions.com\/blog\/powershell\/7921\/answering-the-powershell-linking-challenge\/\" \/>\n<meta property=\"og:locale\" content=\"en_US\" \/>\n<meta property=\"og:type\" content=\"article\" \/>\n<meta property=\"og:title\" content=\"Answering the PowerShell Linking Challenge &#8226; The Lonely Administrator\" \/>\n<meta property=\"og:description\" content=\"My commentary and code on a recent Iron Scripter PowerShell challenge to move and link old files using symbolic links.\" \/>\n<meta property=\"og:url\" content=\"https:\/\/jdhitsolutions.com\/blog\/powershell\/7921\/answering-the-powershell-linking-challenge\/\" \/>\n<meta property=\"og:site_name\" content=\"The Lonely Administrator\" \/>\n<meta property=\"article:published_time\" content=\"2020-12-02T21:46:00+00:00\" \/>\n<meta property=\"article:modified_time\" content=\"2020-12-02T21:46:05+00:00\" \/>\n<meta property=\"og:image\" content=\"https:\/\/jdhitsolutions.com\/blog\/wp-content\/uploads\/2020\/12\/new-item-link-1024x163.png\" \/>\n<meta name=\"author\" content=\"Jeffery Hicks\" \/>\n<meta name=\"twitter:card\" content=\"summary_large_image\" \/>\n<meta name=\"twitter:creator\" content=\"@JeffHicks\" \/>\n<meta name=\"twitter:site\" content=\"@JeffHicks\" \/>\n<meta name=\"twitter:label1\" content=\"Written by\" \/>\n\t<meta name=\"twitter:data1\" content=\"Jeffery Hicks\" \/>\n\t<meta name=\"twitter:label2\" content=\"Est. reading time\" \/>\n\t<meta name=\"twitter:data2\" content=\"8 minutes\" \/>\n<script type=\"application\/ld+json\" class=\"yoast-schema-graph\">{\"@context\":\"https:\\\/\\\/schema.org\",\"@graph\":[{\"@type\":\"Article\",\"@id\":\"https:\\\/\\\/jdhitsolutions.com\\\/blog\\\/powershell\\\/7921\\\/answering-the-powershell-linking-challenge\\\/#article\",\"isPartOf\":{\"@id\":\"https:\\\/\\\/jdhitsolutions.com\\\/blog\\\/powershell\\\/7921\\\/answering-the-powershell-linking-challenge\\\/\"},\"author\":{\"name\":\"Jeffery Hicks\",\"@id\":\"https:\\\/\\\/jdhitsolutions.com\\\/blog\\\/#\\\/schema\\\/person\\\/d0258030b41f07fd745f4078bdf5b6c9\"},\"headline\":\"Answering the PowerShell Linking Challenge\",\"datePublished\":\"2020-12-02T21:46:00+00:00\",\"dateModified\":\"2020-12-02T21:46:05+00:00\",\"mainEntityOfPage\":{\"@id\":\"https:\\\/\\\/jdhitsolutions.com\\\/blog\\\/powershell\\\/7921\\\/answering-the-powershell-linking-challenge\\\/\"},\"wordCount\":812,\"commentCount\":2,\"publisher\":{\"@id\":\"https:\\\/\\\/jdhitsolutions.com\\\/blog\\\/#\\\/schema\\\/person\\\/d0258030b41f07fd745f4078bdf5b6c9\"},\"image\":{\"@id\":\"https:\\\/\\\/jdhitsolutions.com\\\/blog\\\/powershell\\\/7921\\\/answering-the-powershell-linking-challenge\\\/#primaryimage\"},\"thumbnailUrl\":\"https:\\\/\\\/jdhitsolutions.com\\\/blog\\\/wp-content\\\/uploads\\\/2020\\\/12\\\/new-item-link-1024x163.png\",\"articleSection\":[\"PowerShell\"],\"inLanguage\":\"en-US\",\"potentialAction\":[{\"@type\":\"CommentAction\",\"name\":\"Comment\",\"target\":[\"https:\\\/\\\/jdhitsolutions.com\\\/blog\\\/powershell\\\/7921\\\/answering-the-powershell-linking-challenge\\\/#respond\"]}]},{\"@type\":\"WebPage\",\"@id\":\"https:\\\/\\\/jdhitsolutions.com\\\/blog\\\/powershell\\\/7921\\\/answering-the-powershell-linking-challenge\\\/\",\"url\":\"https:\\\/\\\/jdhitsolutions.com\\\/blog\\\/powershell\\\/7921\\\/answering-the-powershell-linking-challenge\\\/\",\"name\":\"Answering the PowerShell Linking Challenge &#8226; The Lonely Administrator\",\"isPartOf\":{\"@id\":\"https:\\\/\\\/jdhitsolutions.com\\\/blog\\\/#website\"},\"primaryImageOfPage\":{\"@id\":\"https:\\\/\\\/jdhitsolutions.com\\\/blog\\\/powershell\\\/7921\\\/answering-the-powershell-linking-challenge\\\/#primaryimage\"},\"image\":{\"@id\":\"https:\\\/\\\/jdhitsolutions.com\\\/blog\\\/powershell\\\/7921\\\/answering-the-powershell-linking-challenge\\\/#primaryimage\"},\"thumbnailUrl\":\"https:\\\/\\\/jdhitsolutions.com\\\/blog\\\/wp-content\\\/uploads\\\/2020\\\/12\\\/new-item-link-1024x163.png\",\"datePublished\":\"2020-12-02T21:46:00+00:00\",\"dateModified\":\"2020-12-02T21:46:05+00:00\",\"description\":\"My commentary and code on a recent Iron Scripter PowerShell challenge to move and link old files using symbolic links.\",\"breadcrumb\":{\"@id\":\"https:\\\/\\\/jdhitsolutions.com\\\/blog\\\/powershell\\\/7921\\\/answering-the-powershell-linking-challenge\\\/#breadcrumb\"},\"inLanguage\":\"en-US\",\"potentialAction\":[{\"@type\":\"ReadAction\",\"target\":[\"https:\\\/\\\/jdhitsolutions.com\\\/blog\\\/powershell\\\/7921\\\/answering-the-powershell-linking-challenge\\\/\"]}]},{\"@type\":\"ImageObject\",\"inLanguage\":\"en-US\",\"@id\":\"https:\\\/\\\/jdhitsolutions.com\\\/blog\\\/powershell\\\/7921\\\/answering-the-powershell-linking-challenge\\\/#primaryimage\",\"url\":\"https:\\\/\\\/jdhitsolutions.com\\\/blog\\\/wp-content\\\/uploads\\\/2020\\\/12\\\/new-item-link.png\",\"contentUrl\":\"https:\\\/\\\/jdhitsolutions.com\\\/blog\\\/wp-content\\\/uploads\\\/2020\\\/12\\\/new-item-link.png\",\"width\":1888,\"height\":300},{\"@type\":\"BreadcrumbList\",\"@id\":\"https:\\\/\\\/jdhitsolutions.com\\\/blog\\\/powershell\\\/7921\\\/answering-the-powershell-linking-challenge\\\/#breadcrumb\",\"itemListElement\":[{\"@type\":\"ListItem\",\"position\":1,\"name\":\"PowerShell\",\"item\":\"https:\\\/\\\/jdhitsolutions.com\\\/blog\\\/category\\\/powershell\\\/\"},{\"@type\":\"ListItem\",\"position\":2,\"name\":\"Answering the PowerShell Linking Challenge\"}]},{\"@type\":\"WebSite\",\"@id\":\"https:\\\/\\\/jdhitsolutions.com\\\/blog\\\/#website\",\"url\":\"https:\\\/\\\/jdhitsolutions.com\\\/blog\\\/\",\"name\":\"The Lonely Administrator\",\"description\":\"Practical Advice for the Automating IT Pro\",\"publisher\":{\"@id\":\"https:\\\/\\\/jdhitsolutions.com\\\/blog\\\/#\\\/schema\\\/person\\\/d0258030b41f07fd745f4078bdf5b6c9\"},\"potentialAction\":[{\"@type\":\"SearchAction\",\"target\":{\"@type\":\"EntryPoint\",\"urlTemplate\":\"https:\\\/\\\/jdhitsolutions.com\\\/blog\\\/?s={search_term_string}\"},\"query-input\":{\"@type\":\"PropertyValueSpecification\",\"valueRequired\":true,\"valueName\":\"search_term_string\"}}],\"inLanguage\":\"en-US\"},{\"@type\":[\"Person\",\"Organization\"],\"@id\":\"https:\\\/\\\/jdhitsolutions.com\\\/blog\\\/#\\\/schema\\\/person\\\/d0258030b41f07fd745f4078bdf5b6c9\",\"name\":\"Jeffery Hicks\",\"image\":{\"@type\":\"ImageObject\",\"inLanguage\":\"en-US\",\"@id\":\"https:\\\/\\\/secure.gravatar.com\\\/avatar\\\/832ae5d438fdcfc1420d720cd1991307927de8a0b12f2342e81c30f773e21098?s=96&d=wavatar&r=pg\",\"url\":\"https:\\\/\\\/secure.gravatar.com\\\/avatar\\\/832ae5d438fdcfc1420d720cd1991307927de8a0b12f2342e81c30f773e21098?s=96&d=wavatar&r=pg\",\"contentUrl\":\"https:\\\/\\\/secure.gravatar.com\\\/avatar\\\/832ae5d438fdcfc1420d720cd1991307927de8a0b12f2342e81c30f773e21098?s=96&d=wavatar&r=pg\",\"caption\":\"Jeffery Hicks\"},\"logo\":{\"@id\":\"https:\\\/\\\/secure.gravatar.com\\\/avatar\\\/832ae5d438fdcfc1420d720cd1991307927de8a0b12f2342e81c30f773e21098?s=96&d=wavatar&r=pg\"}}]}<\/script>\n<!-- \/ Yoast SEO plugin. -->","yoast_head_json":{"title":"Answering the PowerShell Linking Challenge &#8226; The Lonely Administrator","description":"My commentary and code on a recent Iron Scripter PowerShell challenge to move and link old files using symbolic links.","robots":{"index":"index","follow":"follow","max-snippet":"max-snippet:-1","max-image-preview":"max-image-preview:large","max-video-preview":"max-video-preview:-1"},"canonical":"https:\/\/jdhitsolutions.com\/blog\/powershell\/7921\/answering-the-powershell-linking-challenge\/","og_locale":"en_US","og_type":"article","og_title":"Answering the PowerShell Linking Challenge &#8226; The Lonely Administrator","og_description":"My commentary and code on a recent Iron Scripter PowerShell challenge to move and link old files using symbolic links.","og_url":"https:\/\/jdhitsolutions.com\/blog\/powershell\/7921\/answering-the-powershell-linking-challenge\/","og_site_name":"The Lonely Administrator","article_published_time":"2020-12-02T21:46:00+00:00","article_modified_time":"2020-12-02T21:46:05+00:00","og_image":[{"url":"https:\/\/jdhitsolutions.com\/blog\/wp-content\/uploads\/2020\/12\/new-item-link-1024x163.png","type":"","width":"","height":""}],"author":"Jeffery Hicks","twitter_card":"summary_large_image","twitter_creator":"@JeffHicks","twitter_site":"@JeffHicks","twitter_misc":{"Written by":"Jeffery Hicks","Est. reading time":"8 minutes"},"schema":{"@context":"https:\/\/schema.org","@graph":[{"@type":"Article","@id":"https:\/\/jdhitsolutions.com\/blog\/powershell\/7921\/answering-the-powershell-linking-challenge\/#article","isPartOf":{"@id":"https:\/\/jdhitsolutions.com\/blog\/powershell\/7921\/answering-the-powershell-linking-challenge\/"},"author":{"name":"Jeffery Hicks","@id":"https:\/\/jdhitsolutions.com\/blog\/#\/schema\/person\/d0258030b41f07fd745f4078bdf5b6c9"},"headline":"Answering the PowerShell Linking Challenge","datePublished":"2020-12-02T21:46:00+00:00","dateModified":"2020-12-02T21:46:05+00:00","mainEntityOfPage":{"@id":"https:\/\/jdhitsolutions.com\/blog\/powershell\/7921\/answering-the-powershell-linking-challenge\/"},"wordCount":812,"commentCount":2,"publisher":{"@id":"https:\/\/jdhitsolutions.com\/blog\/#\/schema\/person\/d0258030b41f07fd745f4078bdf5b6c9"},"image":{"@id":"https:\/\/jdhitsolutions.com\/blog\/powershell\/7921\/answering-the-powershell-linking-challenge\/#primaryimage"},"thumbnailUrl":"https:\/\/jdhitsolutions.com\/blog\/wp-content\/uploads\/2020\/12\/new-item-link-1024x163.png","articleSection":["PowerShell"],"inLanguage":"en-US","potentialAction":[{"@type":"CommentAction","name":"Comment","target":["https:\/\/jdhitsolutions.com\/blog\/powershell\/7921\/answering-the-powershell-linking-challenge\/#respond"]}]},{"@type":"WebPage","@id":"https:\/\/jdhitsolutions.com\/blog\/powershell\/7921\/answering-the-powershell-linking-challenge\/","url":"https:\/\/jdhitsolutions.com\/blog\/powershell\/7921\/answering-the-powershell-linking-challenge\/","name":"Answering the PowerShell Linking Challenge &#8226; The Lonely Administrator","isPartOf":{"@id":"https:\/\/jdhitsolutions.com\/blog\/#website"},"primaryImageOfPage":{"@id":"https:\/\/jdhitsolutions.com\/blog\/powershell\/7921\/answering-the-powershell-linking-challenge\/#primaryimage"},"image":{"@id":"https:\/\/jdhitsolutions.com\/blog\/powershell\/7921\/answering-the-powershell-linking-challenge\/#primaryimage"},"thumbnailUrl":"https:\/\/jdhitsolutions.com\/blog\/wp-content\/uploads\/2020\/12\/new-item-link-1024x163.png","datePublished":"2020-12-02T21:46:00+00:00","dateModified":"2020-12-02T21:46:05+00:00","description":"My commentary and code on a recent Iron Scripter PowerShell challenge to move and link old files using symbolic links.","breadcrumb":{"@id":"https:\/\/jdhitsolutions.com\/blog\/powershell\/7921\/answering-the-powershell-linking-challenge\/#breadcrumb"},"inLanguage":"en-US","potentialAction":[{"@type":"ReadAction","target":["https:\/\/jdhitsolutions.com\/blog\/powershell\/7921\/answering-the-powershell-linking-challenge\/"]}]},{"@type":"ImageObject","inLanguage":"en-US","@id":"https:\/\/jdhitsolutions.com\/blog\/powershell\/7921\/answering-the-powershell-linking-challenge\/#primaryimage","url":"https:\/\/jdhitsolutions.com\/blog\/wp-content\/uploads\/2020\/12\/new-item-link.png","contentUrl":"https:\/\/jdhitsolutions.com\/blog\/wp-content\/uploads\/2020\/12\/new-item-link.png","width":1888,"height":300},{"@type":"BreadcrumbList","@id":"https:\/\/jdhitsolutions.com\/blog\/powershell\/7921\/answering-the-powershell-linking-challenge\/#breadcrumb","itemListElement":[{"@type":"ListItem","position":1,"name":"PowerShell","item":"https:\/\/jdhitsolutions.com\/blog\/category\/powershell\/"},{"@type":"ListItem","position":2,"name":"Answering the PowerShell Linking Challenge"}]},{"@type":"WebSite","@id":"https:\/\/jdhitsolutions.com\/blog\/#website","url":"https:\/\/jdhitsolutions.com\/blog\/","name":"The Lonely Administrator","description":"Practical Advice for the Automating IT Pro","publisher":{"@id":"https:\/\/jdhitsolutions.com\/blog\/#\/schema\/person\/d0258030b41f07fd745f4078bdf5b6c9"},"potentialAction":[{"@type":"SearchAction","target":{"@type":"EntryPoint","urlTemplate":"https:\/\/jdhitsolutions.com\/blog\/?s={search_term_string}"},"query-input":{"@type":"PropertyValueSpecification","valueRequired":true,"valueName":"search_term_string"}}],"inLanguage":"en-US"},{"@type":["Person","Organization"],"@id":"https:\/\/jdhitsolutions.com\/blog\/#\/schema\/person\/d0258030b41f07fd745f4078bdf5b6c9","name":"Jeffery Hicks","image":{"@type":"ImageObject","inLanguage":"en-US","@id":"https:\/\/secure.gravatar.com\/avatar\/832ae5d438fdcfc1420d720cd1991307927de8a0b12f2342e81c30f773e21098?s=96&d=wavatar&r=pg","url":"https:\/\/secure.gravatar.com\/avatar\/832ae5d438fdcfc1420d720cd1991307927de8a0b12f2342e81c30f773e21098?s=96&d=wavatar&r=pg","contentUrl":"https:\/\/secure.gravatar.com\/avatar\/832ae5d438fdcfc1420d720cd1991307927de8a0b12f2342e81c30f773e21098?s=96&d=wavatar&r=pg","caption":"Jeffery Hicks"},"logo":{"@id":"https:\/\/secure.gravatar.com\/avatar\/832ae5d438fdcfc1420d720cd1991307927de8a0b12f2342e81c30f773e21098?s=96&d=wavatar&r=pg"}}]}},"jetpack_publicize_connections":[],"jetpack_featured_media_url":"","jetpack_sharing_enabled":true,"jetpack_likes_enabled":true,"jetpack-related-posts":[{"id":8107,"url":"https:\/\/jdhitsolutions.com\/blog\/powershell\/8107\/scripting-challenge-meetup\/","url_meta":{"origin":7921,"position":0},"title":"Scripting Challenge Meetup","author":"Jeffery Hicks","date":"February 1, 2021","format":false,"excerpt":"As you probably know, I am the PowerShell problem master behind the challenges from the Iron Scripter site. Solving a PowerShell scripting challenge is a great way to test your skills and expand your knowledge. The final result is merely a means to an end. How you get there and\u2026","rel":"","context":"In &quot;PowerShell&quot;","block_context":{"text":"PowerShell","link":"https:\/\/jdhitsolutions.com\/blog\/category\/powershell\/"},"img":{"alt_text":"","src":"https:\/\/i0.wp.com\/jdhitsolutions.com\/blog\/wp-content\/uploads\/2021\/02\/rubik.jpg?resize=350%2C200&ssl=1","width":350,"height":200},"classes":[]},{"id":129,"url":"https:\/\/jdhitsolutions.com\/blog\/powershell\/129\/practical-powershell\/","url_meta":{"origin":7921,"position":1},"title":"Practical PowerShell","author":"Jeffery Hicks","date":"February 13, 2008","format":false,"excerpt":"I am writing a new monthly column for a new eJournal from RealTime Publishers. The column, Practical PowerShell, will be a regular feature in Windows Administration in Realtime. The eJournal is a free PDF although I think you have to give up an email address. My column is intended to\u2026","rel":"","context":"In &quot;PowerShell&quot;","block_context":{"text":"PowerShell","link":"https:\/\/jdhitsolutions.com\/blog\/category\/powershell\/"},"img":{"alt_text":"","src":"","width":0,"height":0},"classes":[]},{"id":474,"url":"https:\/\/jdhitsolutions.com\/blog\/powershell\/474\/powerpack-challenge-2009-judge\/","url_meta":{"origin":7921,"position":2},"title":"PowerPack Challenge 2009 Judge","author":"Jeffery Hicks","date":"October 28, 2009","format":false,"excerpt":"If you are an active member of the PowerShell community you may have already seen this announcement, but just in case you haven\u2019t, Quest Software and the guys behind PowerGUI are running their annual PowerPack challenge. You could win a $1000 Amazon gift card. The contest ;runs from October 19,\u2026","rel":"","context":"In &quot;PowerShell&quot;","block_context":{"text":"PowerShell","link":"https:\/\/jdhitsolutions.com\/blog\/category\/powershell\/"},"img":{"alt_text":"powergui-train-web","src":"https:\/\/i0.wp.com\/jdhitsolutions.com\/blog\/wp-content\/uploads\/2009\/10\/powerguitrainweb.png?resize=350%2C200","width":350,"height":200},"classes":[]},{"id":1636,"url":"https:\/\/jdhitsolutions.com\/blog\/conferences\/1636\/powershell-deep-dive-europe\/","url_meta":{"origin":7921,"position":3},"title":"PowerShell Deep Dive Europe","author":"Jeffery Hicks","date":"August 29, 2011","format":false,"excerpt":"I'm happy to report that I will be presenting a session at the PowerShell Deep Dive in Frankfurt this October as part of The Experts Conference. The conference in Las Vegas this past April was amazing, intense and the most fun I think I've ever had. If you can make\u2026","rel":"","context":"In &quot;Conferences&quot;","block_context":{"text":"Conferences","link":"https:\/\/jdhitsolutions.com\/blog\/category\/conferences\/"},"img":{"alt_text":"","src":"","width":0,"height":0},"classes":[]},{"id":1454,"url":"https:\/\/jdhitsolutions.com\/blog\/scripting\/1454\/teched-atlanta-managing-the-registry-with-powershell\/","url_meta":{"origin":7921,"position":4},"title":"TechEd Atlanta &#8211; Managing the Registry with PowerShell","author":"Jeffery Hicks","date":"May 23, 2011","format":false,"excerpt":"My second TechEd talk was about managing the registry with Windows PowerShell. If you were in the session you know that I stressed heavily using the PowerShell provider and cmdlets. For remote computers, leverage PowerShell's remoting infrastructure. But I also discussed using the \"raw\" .NET classes as well as WMI\u2026","rel":"","context":"In &quot;Conferences&quot;","block_context":{"text":"Conferences","link":"https:\/\/jdhitsolutions.com\/blog\/category\/conferences\/"},"img":{"alt_text":"","src":"","width":0,"height":0},"classes":[]},{"id":625,"url":"https:\/\/jdhitsolutions.com\/blog\/scripting\/625\/powershell-vs-jesus\/","url_meta":{"origin":7921,"position":5},"title":"PowerShell vs Jesus","author":"Jeffery Hicks","date":"April 15, 2010","format":false,"excerpt":"Ok. I decided it\u2019s time I finally weigh in on this with more than 140 characters. I\u2019m sure you\u2019ve seen, in forums, Twitter and other social media comparisons between Windows PowerShell and some other shell of choice. Typically the \u201cother\u201d shell is LInux based and the comparison is thrown down\u2026","rel":"","context":"In &quot;CommandLine&quot;","block_context":{"text":"CommandLine","link":"https:\/\/jdhitsolutions.com\/blog\/category\/commandline\/"},"img":{"alt_text":"","src":"","width":0,"height":0},"classes":[]}],"_links":{"self":[{"href":"https:\/\/jdhitsolutions.com\/blog\/wp-json\/wp\/v2\/posts\/7921","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/jdhitsolutions.com\/blog\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/jdhitsolutions.com\/blog\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/jdhitsolutions.com\/blog\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/jdhitsolutions.com\/blog\/wp-json\/wp\/v2\/comments?post=7921"}],"version-history":[{"count":0,"href":"https:\/\/jdhitsolutions.com\/blog\/wp-json\/wp\/v2\/posts\/7921\/revisions"}],"wp:attachment":[{"href":"https:\/\/jdhitsolutions.com\/blog\/wp-json\/wp\/v2\/media?parent=7921"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/jdhitsolutions.com\/blog\/wp-json\/wp\/v2\/categories?post=7921"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/jdhitsolutions.com\/blog\/wp-json\/wp\/v2\/tags?post=7921"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}