<?xml version="1.0" encoding="UTF-8"?><rss xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:content="http://purl.org/rss/1.0/modules/content/" xmlns:atom="http://www.w3.org/2005/Atom" version="2.0"><channel><title><![CDATA[Unemployed Philosopher]]></title><description><![CDATA[I am a teacher, a writer, and a dad. I enjoy learning software and writing about my experience. I also love baseball, cooking, and reading old books.]]></description><link>https://johneverettcase.com</link><generator>RSS for Node</generator><lastBuildDate>Wed, 13 May 2026 03:38:13 GMT</lastBuildDate><atom:link href="https://johneverettcase.com/rss.xml" rel="self" type="application/rss+xml"/><language><![CDATA[en]]></language><ttl>60</ttl><item><title><![CDATA[Catch and Store Error Messages in PowerShell]]></title><description><![CDATA[When you are in a flow, nothing is worse than having to stop to deal with a console error message. It would be great if the errors could be handled by the script and packaged into helpful messages. Happily, PowerShell offers this capability to catch,...]]></description><link>https://johneverettcase.com/catch-and-store-error-messages-in-powershell</link><guid isPermaLink="true">https://johneverettcase.com/catch-and-store-error-messages-in-powershell</guid><category><![CDATA[Powershell]]></category><category><![CDATA[try and catch]]></category><dc:creator><![CDATA[John Everett Case]]></dc:creator><pubDate>Wed, 10 May 2023 15:51:44 GMT</pubDate><enclosure url="https://cdn.hashnode.com/res/hashnode/image/stock/unsplash/heNwUmEtZzo/upload/5b8fc560a40dd8d28923c41cf8ae829f.jpeg" length="0" type="image/jpeg"/><content:encoded><![CDATA[<p>When you are in a flow, nothing is worse than having to stop to deal with a console error message. It would be great if the errors could be handled by the script and packaged into helpful messages. Happily, PowerShell offers this capability to catch, store, and take action on error messages when they happen in your code.</p>
<p>Like any good thing, catching and storing errors will require some planning upfront. What type of errors could your script encounter? Are there any actions the script could take when an error has happened? What do you want to do with the error after it has occurred?</p>
<p>Once you have answered these questions, you can begin coding a solution to catch and store any errors. The starting point for your script will be the PowerShell <a target="_blank" href="https://learn.microsoft.com/en-us/powershell/module/microsoft.powershell.core/about/about_try_catch_finally?view=powershell-7.3">try, catch</a> functionality. The try block will be the action taken in your script, and the catch block will be used if an error is encountered during the try action. Different error types can be specified and stored in variables in the catch block. The last error message that was encountered by the script is stored by default in $_ and can be stored in a variable. The example below stores the error in the $LastException variable.</p>
<p>Additionally, you can include multiple catch blocks, to handle specific types of errors and then a general catch block for every other error. The example below looks for an ItemNotFoundException and stores the error in an $ItemNotFound variable.</p>
<pre><code class="lang-powershell"><span class="hljs-keyword">try</span>
{
    <span class="hljs-built_in">Write-Host</span> <span class="hljs-string">"Here are your action steps."</span>
}
<span class="hljs-comment">#This will catch an Item Not Found Exception</span>
<span class="hljs-keyword">catch</span> [<span class="hljs-type">System.Management.Automation.ItemNotFoundException</span>] {
    <span class="hljs-variable">$_</span>.Exception.GetType().Name
    <span class="hljs-variable">$ItemNotFound</span> = <span class="hljs-variable">$_</span>.Exception.GetType().Name
}
<span class="hljs-keyword">catch</span>
{
    <span class="hljs-built_in">Write-Host</span> <span class="hljs-string">"Error: <span class="hljs-variable">$</span>(<span class="hljs-variable">$_</span>)"</span>
    <span class="hljs-variable">$LastException</span> = <span class="hljs-variable">$_</span>
}

<span class="hljs-keyword">if</span> (<span class="hljs-variable">$LastException</span>)
{
    <span class="hljs-built_in">Write-Host</span> <span class="hljs-string">"An error has occurred, the error text is <span class="hljs-variable">$</span>(<span class="hljs-variable">$LastException</span>)."</span>    
}
</code></pre>
<p>These examples should give you a good start toward handling errors in your PowerShell scripts. There are many options for additional handling and adding catch blocks to find and store additional error messages. Thank you for reading!</p>
]]></content:encoded></item><item><title><![CDATA[Git - How to Rebase a Fork]]></title><description><![CDATA[If you have ever forked a repository on github, you have likely encountered the terms merge and rebase when researching how to interact with the original repository. Merging and rebasing are two different methods to solve the same problem, namely, ho...]]></description><link>https://johneverettcase.com/git-how-to-rebase-a-fork</link><guid isPermaLink="true">https://johneverettcase.com/git-how-to-rebase-a-fork</guid><category><![CDATA[Git]]></category><category><![CDATA[GitHub]]></category><category><![CDATA[Rebase]]></category><dc:creator><![CDATA[John Everett Case]]></dc:creator><pubDate>Fri, 02 Dec 2022 17:53:55 GMT</pubDate><enclosure url="https://cdn.hashnode.com/res/hashnode/image/stock/unsplash/eb7a77d15921d7a24b730daaa25ea56d.jpeg" length="0" type="image/jpeg"/><content:encoded><![CDATA[<p>If you have ever forked a repository on github, you have likely encountered the terms merge and rebase when researching how to interact with the original repository. Merging and rebasing are two different methods to solve the same problem, namely, how to keep your fork in sync with the original repository. This post will cover how and when to use rebase, but keep in mind there are specific scenarios in which to use either method.</p>
<p>So let’s say you have forked a github repository so you can contribute some code or documentation. You create a branch of your fork, make your changes, and prepare to make a pull request. But you realize, the original repository has moved on since your fork, meaning, other developers have made commits to it that you don’t have on your local copy. You will need to add those changes to your local copy before making a pull request.</p>
<p>Rebasing will get all the commit to the original repository while saving the changes you made to your local copy. Rebasing will also rewrite the commit history on your forked branch, so it puts your commit at the beginning. This makes for a linear commit history in the original repository.</p>
<p>Keep in mind that rebase should not be done on a public repository where other developers are making commits. Since rebase will rewrite the commit history, it will be confusing other developers working on a project if the entire commit history was rewritten. If, however, you are the only person working on a particular repository, such as a fork, rebase is perfectly applicable and should be used keep a linear commit history.</p>
<p>Once your commits are complete, go to your terminal and change directory to your project. Then follow the list of commands below to rebase from the original repository.</p>
<p>Configure the upstream repository in your project. Change the url to the original repository.</p>
<pre><code>git remote add upstream url
</code></pre><p>Check that the upstream repository is configured.</p>
<pre><code>git remote -v
</code></pre><p>Get the original repository contents.</p>
<pre><code>git fetch upstream
</code></pre><p>Checkout your branch and rebase it with the original repository. Replace main in the checkout statement with your branch name.</p>
<pre><code>git checkout main
git rebase upstream/main
</code></pre><p>Push the rebased repository to your remote forked branch. The --force option may be necessary if there are conflicts between the local and remote repositories. Replace main with your branch name.</p>
<pre><code>git push origin main --force
</code></pre><p>Now you are ready to make a pull request and merge your changes with the original repository.</p>
]]></content:encoded></item><item><title><![CDATA[Git - Add the workflow scope to your Personal Access Token]]></title><description><![CDATA[If you use a personal access token to authenticate to github, and you should be using one, you may have encountered the below error when trying to push updates to a remote repository.
(refusing to allow a Personal Access Token to create or update wor...]]></description><link>https://johneverettcase.com/git-add-the-workflow-scope-to-your-personal-access-token</link><guid isPermaLink="true">https://johneverettcase.com/git-add-the-workflow-scope-to-your-personal-access-token</guid><category><![CDATA[Git]]></category><category><![CDATA[GitHub]]></category><dc:creator><![CDATA[John Everett Case]]></dc:creator><pubDate>Fri, 02 Dec 2022 17:50:48 GMT</pubDate><enclosure url="https://cdn.hashnode.com/res/hashnode/image/stock/unsplash/700261b9fdc3c872db372e527a4089af.jpeg" length="0" type="image/jpeg"/><content:encoded><![CDATA[<p>If you use a personal access token to authenticate to github, and you should be using one, you may have encountered the below error when trying to push updates to a remote repository.</p>
<pre><code>(refusing to allow a Personal Access Token to create or update workflow <span class="hljs-string">`.github/workflows/build_main.yaml`</span> without <span class="hljs-string">`workflow`</span> scope)
</code></pre><p>Frustrating right! Well, fortunately this is easy to fix by following the steps below.</p>
<ol>
<li>Login to GitHub</li>
<li>Go to Settings and choose Developer Settings</li>
<li>Choose Personal Access Tokens</li>
<li>Click the link on the personal access token used for your project</li>
<li>Check the box beside workflow and click Update Token</li>
<li>Click Generate new token and create a save the new token</li>
<li>Change the token in your project to the new one with the workflow scope
Note that you may not need to do steps 6 and 7, it’s best to try your push again after updating to confirm.</li>
</ol>
<p>After updating or generating a new token the workflow scope will be allowed and you can continue on your way.</p>
]]></content:encoded></item><item><title><![CDATA[A Git Primer for Beginners]]></title><description><![CDATA[This short guide is intended to flatten the git learning curve for a beginner. The guide will cover the basics of getting started with git on the command line.
Cloning a Repository
Cloning a repository is the git term for downloading a remote project...]]></description><link>https://johneverettcase.com/a-git-primer-for-beginners</link><guid isPermaLink="true">https://johneverettcase.com/a-git-primer-for-beginners</guid><category><![CDATA[Git]]></category><category><![CDATA[GitHub]]></category><category><![CDATA[Gitcommands]]></category><dc:creator><![CDATA[John Everett Case]]></dc:creator><pubDate>Fri, 02 Dec 2022 17:48:49 GMT</pubDate><enclosure url="https://cdn.hashnode.com/res/hashnode/image/stock/unsplash/0e5f1f01227de8ecca5613c5f442fa66.jpeg" length="0" type="image/jpeg"/><content:encoded><![CDATA[<p>This short guide is intended to flatten the git learning curve for a beginner. The guide will cover the basics of getting started with git on the command line.</p>
<h3 id="heading-cloning-a-repository">Cloning a Repository</h3>
<p>Cloning a repository is the git term for downloading a remote project to your local machine. You can do this with git clone repourl, just replace “repourl” with the url of the repository you want to clone. Doing this on a fork of the original repository is a good idea so you are not trying to commit changes directly to the main branch. Once the command completes, the project files will exist in your local folder. The git metadata, which is how git keeps track of changes, is hidden in the .git folder. To see the metadata files, show hidden files in your git repository folder.</p>
<h3 id="heading-making-changes">Making Changes</h3>
<p>Once you have a current copy of the repository on you local machine, you are ready to begin making changes. After you make changes to a file, make a record of it with git add filepath, and replace “filepath” with the path to the changed file. Repeat git add until you have a record of all the changed files. Then run git status and make sure all the changed files show up.</p>
<h3 id="heading-commit-changes">Commit Changes</h3>
<p>Once your changes are done, it’s time to commit. I know what you’re thinking, but backing out of commits in git is painless! So don’t worry if you commit by mistake. In git, a commit is the record of changes you want to add to the online repository, a line in the sand if you will, that says, I own these changes. If you desire, you can make a commit for each file change; this gives you the option to back out a single change if needed. But if you are brave, you can commit all your changes in one go! The git commit -m "Commit Message" will commit the changes, then the only thing left is to push them to the online repository.</p>
<h3 id="heading-pushing-changes">Pushing Changes</h3>
<p>After committing all your changes, they are ready to be pushed to the online repository. The git push repo branch will achieve this, but note that you will need to change repo and branch to the applicable repository and branch for your setup. If you are working from a fork that you cloned, using “origin” as your repo will likely work. This will push the changes to the repository defined as origin in your git metadata. If you are pushing to a branch of this repository, enter this after repo, but if you are not branching, enter main to push to the main branch. If you are in doubt, open your github repository in the browser and look at the different branches. If no branches exist, just push to the main branch.</p>
<p>This guide demonstrated how to use command line git to clone a repository, add changes, commit changes, and push to an online repository. Learning git can be daunting, but don’t give up! This guide is a great starting point and should encourage you to keep expanding your knowledge.</p>
]]></content:encoded></item><item><title><![CDATA[Fixing Command Not Found in the Mac Terminal]]></title><description><![CDATA[If you have ever installed a new library or language on your mac, you have probably experienced the frustration of receiving “Command Not Found” when trying to use it in the terminal. This is especially challenging for beginners who may wonder what h...]]></description><link>https://johneverettcase.com/fixing-command-not-found-in-the-mac-terminal</link><guid isPermaLink="true">https://johneverettcase.com/fixing-command-not-found-in-the-mac-terminal</guid><category><![CDATA[macOS]]></category><category><![CDATA[terminal]]></category><dc:creator><![CDATA[John Everett Case]]></dc:creator><pubDate>Fri, 02 Dec 2022 16:38:42 GMT</pubDate><enclosure url="https://cdn.hashnode.com/res/hashnode/image/stock/unsplash/dfc573f5bcaa46fd3b64c37366193f1e.jpeg" length="0" type="image/jpeg"/><content:encoded><![CDATA[<p>If you have ever installed a new library or language on your mac, you have probably experienced the frustration of receiving “Command Not Found” when trying to use it in the terminal. This is especially challenging for beginners who may wonder what happened when they installed it in the first place! The good news is, the framework is likely installed correctly, it’s just that the terminal doesn’t know about it yet. So how do you tell the terminal about the new install? If you have this question, read on for some suggestions on how to answer it.</p>
<p>The first thing to know is that the terminal uses an environment variable called $PATH to determine where to look for installed commands. Since this is a variable, it is specific to your environment setup. There are two possible files where the terminal will look for your environment variables. Both are located in you home folder or ~/. To get to this folder in the terminal use cd ~/ or in Finder Cmd+Shift+G. The two files are named .zshrc or .bash_profile, the one in use will depend on which version of the shell you are using. To find this out use echo $SHELL in the Terminal. For zsh the output is /bin/zsh and for bash it is /bin/bash.</p>
<p>Now that you know what shell you are using, you know where to look for your environment variables. Open Terminal and change the directory to /~. Then use the cat command to display the contents of the file in Terminal. If you are using bash, make sure to substitute the bash file for the zsh file in the commands.</p>
<pre><code>cd ~/
cat .zshrc
</code></pre><p>Now you know what is in your file and you should have an idea of what you want to add. To add to the file use the export command in the terminal along with the path to the files you installed. This example will use zsh and ruby 3.0.0 that was installed using homebrew. Keep in mind that the path and application will vary based on what is being installed and how you installed it.</p>
<pre><code>echo <span class="hljs-string">'export PATH="/usr/local/opt/ruby/bin:/usr/local/lib/ruby/gems/3.0.0/bin:$PATH"'</span> &gt;&gt; ~/.zshrc
</code></pre><p>Once the command completes refresh your terminal session by using source ~/.zshrc or by closing the terminal and opening it again. Now when you run your command it should complete without the “Command Not Found” error. You may be asking, where do I find out where my is installed so I know what to add to my PATH. The answer to this depends on how the package was installed, and what version it is. In the logs from your package manager it will likely have the install location. If this is not available try searching for the default install location for your package manager and look there. If you still can’t find it, try installing the package again and see if the logs will tell you where it put the files.</p>
]]></content:encoded></item><item><title><![CDATA[How to install PowerShell modules on an offline computer]]></title><description><![CDATA[Installing powershell modules is simple, right? Open a powershell window and use the Find-Module cmdlet or if you know the name of the module go straight to Install-Module. This will connect to the PowerShell gallery and download and install the modu...]]></description><link>https://johneverettcase.com/how-to-install-powershell-modules-on-an-offline-computer</link><guid isPermaLink="true">https://johneverettcase.com/how-to-install-powershell-modules-on-an-offline-computer</guid><category><![CDATA[Powershell]]></category><dc:creator><![CDATA[John Everett Case]]></dc:creator><pubDate>Thu, 01 Dec 2022 19:20:36 GMT</pubDate><enclosure url="https://cdn.hashnode.com/res/hashnode/image/unsplash/EJe6LqEjHpA/upload/v1669922103339/HeU6VcCwS.jpeg" length="0" type="image/jpeg"/><content:encoded><![CDATA[<p>Installing powershell modules is simple, right? Open a powershell window and use the <a target="_blank" href="https://docs.microsoft.com/en-us/powershell/module/powershellget/find-module?view=powershell-7.1">Find-Module</a> cmdlet or if you know the name of the module go straight to <a target="_blank" href="https://docs.microsoft.com/en-us/powershell/module/powershellget/install-module?view=powershell-7.1">Install-Module</a>. This will connect to the <a target="_blank" href="https://www.powershellgallery.com/">PowerShell gallery</a> and download and install the module for you. But what if the computer that needs the new module is not connected to the internet? If you are facing this challenge, you have come to the right place. This guide will take you step-by-step through the process.</p>
<p>Please note that powershell modules are not compatible with every powershell version, remember to check the module prerequisites before installing it on the desired computer.</p>
<h3 id="heading-prerequisites">Prerequisites</h3>
<p>Here are the prerequisites you will need to complete the steps in this guide.</p>
<p>A Windows computer, connected to the internet.
The name of the powershell module you want to install.
The path where you will save the module on your computer.</p>
<h3 id="heading-installing-the-module">Installing the Module</h3>
<p>The first step for installing a PowerShell module on an offline computer is to download it with a computer that is connected to the internet.</p>
<ol>
<li>In the Start menu search for the Windows Powershell application and open it.</li>
<li>On the command line type Save-Module -Name ModuleName -Path “FilePath” and Enter to run the command. 
  Remember to replace ModuleName and FilePath with the values needed for your use case.</li>
<li>The module will now be saved into the folder defined in the -Path parameter. Browse to this location in File Explorer.</li>
</ol>
<p>The next step is to move the module folder to the offline computer and import it into powershell.</p>
<ol>
<li>Copy the folder you located in step 3 and paste it on the offline computer in the following location, C:\Program 
 Files\WindowsPowerShell\Modules.</li>
<li>On the offline computer, search for Windows PowerShell in the Start menu and open it.</li>
<li>On the command line type Import-Module -Name ModuleName and Enter to run the command. Please note that the 
 name entered on the command line needs to match the folder name copied in step 4.</li>
</ol>
<p>The module has now been installed on the offline computer, congratulations!</p>
]]></content:encoded></item><item><title><![CDATA[All about renaming files with PowerShell]]></title><description><![CDATA[Renaming files is a common operation in windows, it’s simple enough to select a file and rename it using the context menu. But what if you have many files or need to automate file renaming? PowerShell reduces this operation to several simple commands...]]></description><link>https://johneverettcase.com/all-about-renaming-files-with-powershell</link><guid isPermaLink="true">https://johneverettcase.com/all-about-renaming-files-with-powershell</guid><category><![CDATA[Powershell]]></category><dc:creator><![CDATA[John Everett Case]]></dc:creator><pubDate>Thu, 01 Dec 2022 19:11:37 GMT</pubDate><enclosure url="https://cdn.hashnode.com/res/hashnode/image/unsplash/tQQ4BwN_UFs/upload/v1669921825419/tobe25_it.jpeg" length="0" type="image/jpeg"/><content:encoded><![CDATA[<p>Renaming files is a common operation in windows, it’s simple enough to select a file and rename it using the context menu. But what if you have many files or need to automate file renaming? PowerShell reduces this operation to several simple commands with a for each object loop.</p>
<pre><code>$filelist = (Get-ChildItem “C:\FilePath\*.*” | foreach-object {$_.name})
foreach ($file <span class="hljs-keyword">in</span> $filelist)
{
$newname = ‘customString’ + $file + ‘.file’
Rename-Item “C:\FilePath\$file” $newname -verbose
clear-variable newname
}
</code></pre><p>Begin by searching for the file you want to rename. The Get-ChildItem command will find the list of files and pass it to foreach-object. This is all stored in the $filelist variable. Then a foreach loop is created in which a new file name is given to each file. The $newname variable will control how the file is named with the $file section being the original file name. This original file name can be replaced with whatever is needed for your circumstance. Dates and times can also be added to the name by using Get-Date and formatting the date and time as desired. The new name is then passed to the Rename-Item command to perform the rename operation. Finally the newname variable is cleared so it can be used in the next loop.</p>
]]></content:encoded></item><item><title><![CDATA[How to compare file lengths with PowerShell]]></title><description><![CDATA[After a file copy is complete, how can you be sure the entire file was copied? This can be done with the file length command in PowerShell. This will compare the length in bytes of each file and, combined with an if statement, is a way to perform rem...]]></description><link>https://johneverettcase.com/how-to-compare-file-lengths-with-powershell</link><guid isPermaLink="true">https://johneverettcase.com/how-to-compare-file-lengths-with-powershell</guid><category><![CDATA[Powershell]]></category><dc:creator><![CDATA[John Everett Case]]></dc:creator><pubDate>Thu, 01 Dec 2022 19:07:45 GMT</pubDate><enclosure url="https://cdn.hashnode.com/res/hashnode/image/unsplash/Q9y3LRuuxmg/upload/v1669921595933/imUxuusM8.jpeg" length="0" type="image/jpeg"/><content:encoded><![CDATA[<p>After a file copy is complete, how can you be sure the entire file was copied? This can be done with the file length command in PowerShell. This will compare the length in bytes of each file and, combined with an if statement, is a way to perform remediation on a failed file copy automatically.</p>
<p>First, store each file contents in memory using variables and the Get-Item command. Then compare them with an if statement using the file.Length command. The space in the else rackets can be used to take appropriate action if the file lengths do not match.</p>
<pre><code>$file1 = Get-Item ‘C:\FilePath\File1.file’ -Verbose
$file2 = Get-Item ‘C:\FilePath\File2.file’ -Verbose
If ($file1.Length -eq $file2.Length)
{ Write-Host “File Sizes Match” }
<span class="hljs-keyword">else</span>
{ Write-Host “File Sizes Do Not Match” }
</code></pre>]]></content:encoded></item><item><title><![CDATA[How to check a Windows Service status with PowerShell]]></title><description><![CDATA[PowerShell offers simple ways to perform administrative tasks such as checking the status of a service. This can be combined with an if statement to act on a stopped service automatically. These commands can be incorporated into a much larger script ...]]></description><link>https://johneverettcase.com/how-to-check-a-windows-service-status-with-powershell</link><guid isPermaLink="true">https://johneverettcase.com/how-to-check-a-windows-service-status-with-powershell</guid><category><![CDATA[Powershell]]></category><category><![CDATA[Windows]]></category><dc:creator><![CDATA[John Everett Case]]></dc:creator><pubDate>Wed, 30 Nov 2022 16:24:28 GMT</pubDate><enclosure url="https://cdn.hashnode.com/res/hashnode/image/unsplash/UQ2Fw_9oApU/upload/v1669825346589/xVsxljpBZ.jpeg" length="0" type="image/jpeg"/><content:encoded><![CDATA[<p>PowerShell offers simple ways to perform administrative tasks such as checking the status of a service. This can be combined with an if statement to act on a stopped service automatically. These commands can be incorporated into a much larger script to check multiple services.</p>
<p>The first step is to store the service name in the variable <strong>$ServiceName</strong>. Then you can use another variable to store the service information which contains the status information. The <strong>Get-Service</strong> command can be used to retrieve this information.</p>
<p>Then, using an <strong>if</strong> statement, you can compare the service info status to a static value. In the example, the service info status is checked against the value <strong>Running</strong> which determines whether is started and running. The actions can then be taken on the service such as starting it or alerting the appropriate parties. In the example, the script attempts to start the service, then performs a refresh of the service information and writes the new status to the console log.</p>
<pre><code class="lang-bash"><span class="hljs-variable">$ServiceName</span> = ‘Service’
<span class="hljs-variable">$ServiceInfo</span> = Get-Service -Name <span class="hljs-variable">$ServiceName</span>
<span class="hljs-keyword">if</span> (<span class="hljs-variable">$ServiceInfo</span>.Status -ne ‘Running’) {
write-host ‘service is not started, starting service’
Start-Service -Name <span class="hljs-variable">$ServiceName</span> -verbose
<span class="hljs-variable">$ServiceInfo</span>.Refresh()
write-host <span class="hljs-variable">$ServiceInfo</span>.Status
}
write-host ‘all <span class="hljs-keyword">done</span>’
</code></pre>
]]></content:encoded></item><item><title><![CDATA[How to remove files by last write time with PowerShell]]></title><description><![CDATA[Drive space is a finite resource, ask any server administrator. No one wants to see the message, “No space on disk”, when you are trying to save that last document. How can you clean up files that you don’t need? As always, PowerShell makes it simple...]]></description><link>https://johneverettcase.com/how-to-remove-files-by-last-write-time-with-powershell</link><guid isPermaLink="true">https://johneverettcase.com/how-to-remove-files-by-last-write-time-with-powershell</guid><category><![CDATA[Powershell]]></category><dc:creator><![CDATA[John Everett Case]]></dc:creator><pubDate>Tue, 29 Nov 2022 17:42:39 GMT</pubDate><enclosure url="https://cdn.hashnode.com/res/hashnode/image/unsplash/7EwWeNyzSwQ/upload/v1669743465377/8zJJBNxw6.jpeg" length="0" type="image/jpeg"/><content:encoded><![CDATA[<p>Drive space is a finite resource, ask any server administrator. No one wants to see the message, “No space on disk”, when you are trying to save that last document. How can you clean up files that you don’t need? As always, PowerShell makes it simple.</p>
<p>This script will remove files by last write time, which is the last date and time the file was modified.</p>
<pre><code>$Now=Get-<span class="hljs-built_in">Date</span>
Get-Childitem C:\FilePath\*.* | Where-<span class="hljs-built_in">Object</span> { $_.LastWriteTime -lt $Now.AddDays(<span class="hljs-number">-30</span>) } | Remove-Item -Verbose
</code></pre><p>The first step is to get the time you want to use as the baseline for the delete, this is what you will compare against when telling the script what files to remove. In the example, this date and time is stored in the variable $Now. The Get-Date command will retrieve the date and time when the script is run.</p>
<p>The next step is to get a list of files that are candidates for removal. This is done with the Get-ChildItem command and the file path. This information is sent to the Where-Object command which determines which files meet the criteria. In the example, last write time is used along with $Now.AddDays(-30) which subtracts 30 days from the current date. Any files where the last write time is more than 30 days old are then sent to the Remove-Item command and deleted.</p>
]]></content:encoded></item><item><title><![CDATA[How to cast a string value as an integer in PowerShell]]></title><description><![CDATA[When numbers are stored as a string in a database, it is difficult to sort them, so they are readable to human users. PowerShell makes this operation simple, to take a string value, cast it as an integer, sort it by numeric value and create an output...]]></description><link>https://johneverettcase.com/how-to-cast-a-string-value-as-an-integer-in-powershell</link><guid isPermaLink="true">https://johneverettcase.com/how-to-cast-a-string-value-as-an-integer-in-powershell</guid><category><![CDATA[Powershell]]></category><category><![CDATA[string]]></category><category><![CDATA[integer]]></category><dc:creator><![CDATA[John Everett Case]]></dc:creator><pubDate>Mon, 28 Nov 2022 15:24:13 GMT</pubDate><enclosure url="https://cdn.hashnode.com/res/hashnode/image/unsplash/mdADGzyXCVE/upload/v1669649032805/ZdFOaWCKF.jpeg" length="0" type="image/jpeg"/><content:encoded><![CDATA[<p>When numbers are stored as a string in a database, it is difficult to sort them, so they are readable to human users. PowerShell makes this operation simple, to take a string value, cast it as an integer, sort it by numeric value and create an output file with the sorted values.</p>
<p>To perform this operation, use the code here.</p>
<pre><code>$SortValues = Get-Content -Path C:\FilePath\FileName.file | ForEach-<span class="hljs-built_in">Object</span> -Process {[int]$_} | Sort-<span class="hljs-built_in">Object</span>
$SortValues | ForEach-<span class="hljs-built_in">Object</span> {$_.ToString(“<span class="hljs-number">0000000000000000</span>”)} | Out-File -FilePath C:\FilePath\SortedFileName.file
</code></pre><p>The code assumes that the values are stored in a file, with the first command retrieving the data from the file. This data is then sent to the ForEach-Object command which casts the string values as integers and then sorts each value in ascending order. This data is stored in the variable $SortValues which can then be used to create an output file in the second command.</p>
<p>The second command takes the data stored in the $SortValues variable and makes sure each value is 16 characters, meaning it will add leading zeroes where necessary. Please note, that this step is not necessary, if you want to simply output the values as they are to a file, this section can be removed, leaving the Out-File command. The Out-File command then creates an output file with the values sorted by number. </p>
]]></content:encoded></item><item><title><![CDATA[How to remove duplicate files with PowerShell]]></title><description><![CDATA[So, you have a folder full of files, the names look similar, and you’re not sure what is in them. Storage space is tight, and you do not want to keep duplicate copies. How can you remove the duplicate files while avoiding the painstaking work of sort...]]></description><link>https://johneverettcase.com/how-to-remove-duplicate-files-with-powershell</link><guid isPermaLink="true">https://johneverettcase.com/how-to-remove-duplicate-files-with-powershell</guid><category><![CDATA[Powershell]]></category><category><![CDATA[Windows]]></category><dc:creator><![CDATA[John Everett Case]]></dc:creator><pubDate>Mon, 21 Nov 2022 18:02:56 GMT</pubDate><enclosure url="https://cdn.hashnode.com/res/hashnode/image/unsplash/fPxOowbR6ls/upload/v1669053759268/a_xTHtsX2.jpeg" length="0" type="image/jpeg"/><content:encoded><![CDATA[<p>So, you have a folder full of files, the names look similar, and you’re not sure what is in them. Storage space is tight, and you do not want to keep duplicate copies. How can you remove the duplicate files while avoiding the painstaking work of sorting through each one? With PowerShell and file hashes, the answer is, surprisingly easy. For files that are exact copies of each other, the file hash is the same, so the operation is to find the file hashes for a group of files and remove only one of the duplicates. Here is the complete operation to remove duplicate files with an explanation that follows.</p>
<pre><code>Get-ChildItem “C:\FilePath\*FileName.file” | Get-FileHash | Group-<span class="hljs-built_in">Object</span> -property hash | Where-<span class="hljs-built_in">Object</span> { $_.count -gt <span class="hljs-number">1</span> } | ForEach-<span class="hljs-built_in">Object</span> { $_.group | Select-<span class="hljs-built_in">Object</span> -skip <span class="hljs-number">1</span> } | Remove-Item -Verbose
</code></pre><p>The first step is to get a list of the files that are duplicated, this is done with Get-ChildItem and the path and name of the files. This list is then sent to the Get-FileHash command which retrieves the file hash for each file in the list. The file hashes are then grouped by the hash number with Group-Object so the duplicate file hashes will be next to each other in the list. This is important for the next step.</p>
<p>The grouped list is then sent to Where-Object which counts the list for file hashes where the value is greater than one. This will identify only the duplicated files from the list. The grouped objects are then sent to ForEach-Object which creates a loop to run through each set of duplicate files. In each duplicate object set, one file is skipped and not retained in the list that is sent to Remove-Item to delete the file. Now duplicates should have been removed.</p>
]]></content:encoded></item><item><title><![CDATA[Evaluating (s)ftp exit codes]]></title><description><![CDATA[By design, ftp interfaces are simple. Connect to a server, get or put and file and disconnect. This has advantages, it is simple to learn and to use, the barrier to entry is low and changes to syntax are few. This is ideal for ad hoc transfers to and...]]></description><link>https://johneverettcase.com/evaluating-sftp-exit-codes</link><guid isPermaLink="true">https://johneverettcase.com/evaluating-sftp-exit-codes</guid><category><![CDATA[windows server]]></category><category><![CDATA[SFTP]]></category><dc:creator><![CDATA[John Everett Case]]></dc:creator><pubDate>Thu, 17 Nov 2022 17:15:43 GMT</pubDate><enclosure url="https://cdn.hashnode.com/res/hashnode/image/unsplash/f77Bh3inUpE/upload/v1669053827562/ACjlfJnAE.jpeg" length="0" type="image/jpeg"/><content:encoded><![CDATA[<p>By design, ftp interfaces are simple. Connect to a server, get or put and file and disconnect. This has advantages, it is simple to learn and to use, the barrier to entry is low and changes to syntax are few. This is ideal for ad hoc transfers to and from a server, but for automated transfers this can pose challenges.</p>
<p>When performing an ad hoc transfer, it is easy to see when a transfer fails and take action to correct it. But when using automation for file transfers, this becomes difficult. How do you know when a transfer fails and how it should be corrected? A first step toward this is evaluating the exit code of the ftp script. This would indicate if the script completed all steps successfully or not. It will not indicate exactly what failed, this will require further investigation. The exit codes are zero for success and one for failure. There is some variation in exit codes between ftp clients but zero is always success and one is always a type of failure. Evaluating the exit code for non-zero values would indicate whether a script failed and needs further review.</p>
<p>To evaluate the exit code, add the following line to the end of a shell script in Windows after the ftp commands have completed.</p>
<pre><code>IF %ERRORLEVEL% EQU <span class="hljs-number">0</span> Echo Success &gt; “Path to File”
</code></pre><p>This line will check if the exit code is zero and write the word “Success” to a defined file. Evaluating the exit code is not limited to this type of interaction, using the if statement above, any number of actions can be performed after the exit code is evaluated. For instance, if the exit code is not equal to zero a message could be sent to indicate further review is needed. The exit code could also be consumed by another monitoring tool which would allow for automated alerting in cases where many transfers need to be evaluated. The options are only limited to your imagination but evaluating the exit code is the entry point for knowing if a file transfer was successful.</p>
]]></content:encoded></item><item><title><![CDATA[How to check for multiple files with PowerShell]]></title><description><![CDATA[In PowerShell, checking for a file is as simple as using the Test-Path command with the file path. Followed by an if statement, this is a great tool to check when a file exists. If the result of Test-Path is stored in a variable, this can be used to ...]]></description><link>https://johneverettcase.com/how-to-check-for-multiple-files-with-powershell</link><guid isPermaLink="true">https://johneverettcase.com/how-to-check-for-multiple-files-with-powershell</guid><category><![CDATA[Powershell]]></category><dc:creator><![CDATA[John Everett Case]]></dc:creator><pubDate>Wed, 16 Nov 2022 18:06:30 GMT</pubDate><enclosure url="https://cdn.hashnode.com/res/hashnode/image/unsplash/d9ILr-dbEdg/upload/v1669053866543/0cVArPKjo.jpeg" length="0" type="image/jpeg"/><content:encoded><![CDATA[<p>In PowerShell, checking for a file is as simple as using the Test-Path command with the file path. Followed by an if statement, this is a great tool to check when a file exists. If the result of Test-Path is stored in a variable, this can be used to evaluate the result and proceed, as necessary.</p>
<p>But what if multiple files are needed before acting? The Test-Path command can accept an array with each path being separated by commas. While checking the result for a single file is a simple True/False statement, checking the result of a Test-Path array is more difficult. When the result of a Test-Path array is stored in a variable, it stores the result of each file path check. All the file paths may evaluate to True, False, or a combination of both. This means, when checking the result, it is necessary to accept one desired outcome and discard all others.</p>
<p>For example, to accept only an outcome where all file paths evaluate to True, the -notcontains $false modifier can be used on Test-Path. This will ignore any outcomes that are false meaning the whole Test-Path statement will only be True when all file paths in the array are True. The same logic can be used in reverse if the desired outcome is for all of the paths to be False.</p>
<p>Here is an example of how to use an array with Test-Path. In this example the $result variable will only be true if all paths in the array exist.</p>
<pre><code>$filecheck = “File Path <span class="hljs-number">1</span>”, “File Path <span class="hljs-number">2</span>”, “File Path <span class="hljs-number">3</span>”
$result = ($filecheck | Test-Path) -notcontains $false
</code></pre>]]></content:encoded></item><item><title><![CDATA[PGP Encryption and Temporary Home Directories]]></title><description><![CDATA[GPG is used as back-end encryption for many applications and processes, as such, it’s necessary to have a reusable key implementation routine. This is where the home directory comes in; the home directory can be used to cache keys for repeated use ev...]]></description><link>https://johneverettcase.com/pgp-encryption-and-temporary-home-directories</link><guid isPermaLink="true">https://johneverettcase.com/pgp-encryption-and-temporary-home-directories</guid><category><![CDATA[Powershell]]></category><category><![CDATA[gpg]]></category><category><![CDATA[PGP]]></category><dc:creator><![CDATA[John Everett Case]]></dc:creator><pubDate>Tue, 15 Nov 2022 20:45:02 GMT</pubDate><enclosure url="https://cdn.hashnode.com/res/hashnode/image/unsplash/OjSG0E_qcbo/upload/v1669053903889/WyD42X_EY.jpeg" length="0" type="image/jpeg"/><content:encoded><![CDATA[<p>GPG is used as back-end encryption for many applications and processes, as such, it’s necessary to have a reusable key implementation routine. This is where the home directory comes in; the home directory can be used to cache keys for repeated use even when the user executing the task does not own the keys.</p>
<p>To set a home directory, the — <strong>homedir</strong> switch can be used on the command line followed by the path to the home directory. Typically, this will be a copy of gnupg folder after the applicable keys have been created or imported and trusted. This type of setup is could be effective in a single-use context, but not in a scenario where file decryption needs to happen repeatedly. The reason for this is because of how the gpg agent interacts with the home directory. The gpg agent starts when it is called and ends when the interaction has ceased. But when using a home directory, the normal termination of the gpg agent is not allowed to occur and can leave the agent thread running in the background. This can have unintended consequences such as interrupting repeated processes that are attempting to use the same home directory.</p>
<p>The simplest solution to this is temporary home directories. Recursively copying, using, and then removing a home directory will reliably start, engage, and end the gpg agent thread, allowing for repeated use. The removal of the home directory indicates to the gpg agent that the process is complete, and it can end.</p>
]]></content:encoded></item></channel></rss>