I Asked ChatGPT How to Resolve a Symlink in PowerShell
Latest update:
The only job I have found for ChatGPT is to fix my grammar. For every
other task, it only wastes my time.
Here's a very easy problem. Install vnu on Windows 10 so that:
d:/opt/s/vnu/dist/
directory contains vnu.jar file.
d:/opt/s/vnu/vnu.ps1
script runs the .jar.
d:/opt/bin/vnu.ps1
is a symlink to the item #2.
d:/opt/bin/
is in PATH, hence when I run vnu.ps1
is should
correctly invoke the .jar file. If you're a Windows user, you can
probably write a corresponding powershell script with your eyes
closed. But what if you're not a Windows user & are only familiar
with bash? Suppose Google is down & all we have is ChatGPT?
Some preliminaries:
> scoop bucket add java
> scoop install oraclejdk
> mkdir -p d:/opt/s/vnu
> cd d:/opt/s/vnu
> wget.exe https://github.com/validator/validator/releases/download/20.6.30/vnu.jar_20.6.30.zip
> unzip *zip
OK, our 1st version is:
> pwd
Path
----
D:\opt\s\vnu
> cat vnu.ps1
$jar = "dist/vnu.jar"
java -jar $jar --asciiquotes --also-check-css $args
> ./vnu.ps1 --version
20.6.30
We, of course, are going to run the script in different directories,
e.g.:
> cd ..
> .\vnu\vnu.ps1 --version
Error: Unable to access jarfile dist/vnu.jar
That was expected. What we are looking for here is to put $(dirname $(readlink -f $0))
into our script.
me: powershell equivalent of $(dirname $(readlink -f $0))
chatgpt: The PowerShell equivalent of the Bash command $(dirname
$(readlink -f $0)), which returns the directory of the currently
executing script, would be:
$scriptDir = Split-Path -Path $MyInvocation.MyCommand.Definition -Parent
Hm, seems too easy:
> cat vnu/vnu.ps1
$dir = Split-Path -Path $MyInvocation.MyCommand.Definition -Parent
$jar = "$dir/dist/vnu.jar"
java -jar $jar --asciiquotes --also-check-css $args
But to test the new version, we also need to create a symlink to
it. Um,
me: create a symlink in powershell
chatgpt: To create a symbolic link (symlink) in PowerShell, you can
use the New-Item cmdlet with the -ItemType SymbolicLink
parameter. The New-Item cmdlet creates a new file, directory, or
other item, and the -ItemType parameter specifies the type of item
to create. Here is an example:
New-Item -ItemType SymbolicLink -Path "C:\Users\Username\Desktop\Link" -Target "C:\Users\Username\Documents"
OK, seems fine.
> cd d:/opt/bin
> New-Item -ItemType SymbolicLink -target ..\s\vnu\vnu.ps1 -path vnu.ps1
New-Item : Administrator privilege required for this operation.
JFC, why, Microsoft, why? Anyway:
me: how do I run the command you provided as an administrator? is
there a sudo equivalent?
chatgpt: To run a PowerShell command as an administrator, you can use
the Start-Process cmdlet with the -Verb RunAs parameter. This
parameter opens the process with administrative privileges, similar to
the sudo command in Linux. Here's an example:
Start-Process powershell -Verb RunAs -ArgumentList "New-Item -ItemType SymbolicLink -Path 'C:\Users\Username\Desktop\Link' -Target 'C:\Users\Username\Documents'"
This looks rather idiotic, but when dutifully typed:
> Start-Process powershell -Verb RunAs -ArgumentList "New-Item -ItemType SymbolicLink -target ..\s\vnu\vnu.ps1 -path vnu.ps1"
it, of course, failed miserably. It indeed displayed a UAC prompt, but
then a blue powershell terminal window blanked out for a fraction of a
second. I presume it printed an error, but it was so quick to exit
that I couldn't read the message. If you rerun the command as
> Start-Process powershell -Verb RunAs -ArgumentList "powershell"
it opens the blue powershell terminal with C:\Windows\system32
as
the current working directory. Unhelpful if you're trying to create a
relative symlink. Anyway I manually did 'cd' & rerun New-Item
command (it worked). Then
> pwd
Path
----
D:\opt\bin
> .\vnu.ps1 -version
Error: Unable to access jarfile D:\opt\bin/dist/vnu.jar
Yep. So $MyInvocation.MyCommand.Definition
!= $(readlink -f $0)
. Somehow, I suspected that. Let's start from the beginning.
me: powershell equivalent of bash $0
chatgpt: The PowerShell equivalent of the Bash variable $0, which
contains the name of the currently executing script, would be:
$MyInvocation.MyCommand.Name
OK, we already saw that split-path
~= basename
, hence:
> cat ..\s\vnu\vnu.ps1
$dir = split-path $MyInvocation.MyCommand.Name
$jar = "$dir/dist/vnu.jar"
java -jar $jar --asciiquotes --also-check-css $args
Will it work if $MyInvocation.MyCommand
is a symlink? No it won't:
> ./vnu.ps1
Error: Unable to access jarfile /dist/vnu.jar
WTF, $dir
is empty!
me: briefly describe powershell's $MyInvocation.MyCommand
chatgpt: In PowerShell, the $MyInvocation automatic variable contains
information about the current script or command invocation. One of the
properties of $MyInvocation is MyCommand, which is an object that
represents the current script or command.
The MyCommand object has several properties, including:
Name: The name of the script or command.
Definition: The full path of the script or command.
Fine:
> cat ..\s\vnu\vnu.ps1
$dir = split-path $MyInvocation.MyCommand.Definition
$jar = "$dir/dist/vnu.jar"
java -jar $jar --asciiquotes --also-check-css $args
> ./vnu.ps1
Error: Unable to access jarfile D:\opt\bin/dist/vnu.jar
Woo-hoo, we got "basename $0" working (again)! Amazing achievement.
me: powershell equivalent of linux readlink -f
chatgpt: The PowerShell equivalent of the Linux command readlink -f
would be the following command:
(Get-Item -Path "path\to\file").FullName
Really? Well, what do I know, who am I to question our overlords:
> cat ..\s\vnu\vnu.ps1
$script = (Get-Item -Path $MyInvocation.MyCommand.Definition).FullName
$dir = split-path $script
$jar = "$dir/dist/vnu.jar"
java -jar $jar --asciiquotes --also-check-css $args
> ./vnu.ps1
Error: Unable to access jarfile D:\opt\bin/dist/vnu.jar
This is not even funny anymore, apparently Get-Item
didn't resolve
anything.
me: resolve a symlink in powershell
chatgpt: To resolve a symbolic link (symlink) and get the target path
in PowerShell, you can use the Resolve-Path cmdlet with the -Path
parameter. Here's an example:
$targetPath = Resolve-Path -Path "C:\path\to\symlink"
Nope:
> cat ..\s\vnu\vnu.ps1
$script = Resolve-Path -Path $MyInvocation.MyCommand.Definition
$dir = split-path $script
$jar = "$dir/dist/vnu.jar"
java -jar $jar --asciiquotes --also-check-css $args
> ./vnu.ps1
Error: Unable to access jarfile D:\opt\bin/dist/vnu.jar
Before I give up & google, let's try something different, ask the bot
to rewrite a 100% working shell script:
me: rewrite a bash script in powershell:
#!/bin/sh
dir=$(dirname "$(readlink -f "$0")")
jar="$dir/dist/vnu.jar"
java -jar "$jar" --asciiquotes --also-check-css "$@"
chatgpt: Here's how you can rewrite the Bash script in PowerShell:
$dir = Split-Path -Path (Resolve-Path -Path $MyInvocation.MyCommand.Path) -Parent
$jar = "$dir\dist\vnu.jar"
java -jar $jar --asciiquotes --also-check-css $args
I think you can see the problem here. I couldn't take it any longer &
googled 'resolve symlink in powershell'. Here's the final script that
works:
> cat ..\s\vnu\vnu.ps1
$script = (get-item $MyInvocation.MyCommand.Definition).target
$dir = split-path $script
$jar = "$dir/dist/vnu.jar"
java -jar $jar --asciiquotes --also-check-css $args
> ./vnu.ps1 --version
20.6.30
Enjoy the future.
Tags: ойті
Authors: ag