<?xml version="1.0" encoding="UTF-8"?><rss version="2.0" xmlns:content="http://purl.org/rss/1.0/modules/content/">
  <channel>
    <title>bash &amp;mdash; StealthyCoder</title>
    <link>https://stealthycoder.writeas.com/tag:bash</link>
    <description>Making code ninjas out of everyone</description>
    <pubDate>Tue, 19 May 2026 11:37:27 +0000</pubDate>
    <item>
      <title>Crucible</title>
      <link>https://stealthycoder.writeas.com/crucible?pk_campaign=rss-feed</link>
      <description>&lt;![CDATA[I am currently working on and off on a side project and I named it crucible. It is to do with Shell scripts and I will explain briefly what it does and how. !--more--&#xA;Why crucible?&#xA;&#xA;So the idea was to first name it anvil or ansible but those two names already exist in the DevOps world as other tools. So then I came up with the idea of a framework that can mould things and then you pour it like from a crucible into whatever shape you chose to make and replicate the scripts completely. In essence I wanted to make a virtualenv for shell scripts.&#xA;&#xA;The obvious question is why do I wanted to make this. So the reason was mainly to have a nice framework for repeatable and quickly made shell scripts. All those manipulations that you might forget over time and only occasionally need. Like arrays in Bash, or date times, or navigation. There exist a collection of Bash functions but it was not nearly as nicely structured and you had to manually source them.&#xA;&#xA;In addition to this all, I just wanted to see how far I can take one language that is designed to do a very limited set of things. See how far I can take this limited set and make it do things that are normal in other programming languages. &#xA;&#xA;Structure&#xA;&#xA;The structure of the side project is that for each of the shells I want to target:&#xA;&#xA;Bash&#xA;Fish&#xA;ksh&#xA;csh&#xA;zsh&#xA;&#xA;I will have written functions that you can require. The entrypoint of the main shell script is a file called .mould . It contains the require function logic. Basically it will download the requirements and source them into your current script. &#xA;&#xA;Then when you are done you call the pour command and it will produce a tarball that will hold the full script with dependencies so you can run it anywhere and everywhere. &#xA;&#xA;Example functions&#xA;&#xA;For example I made some functions pertaining to dealing with arrays in the shell. There even exists a map functionality that applies a function to every element of the array and thereby transforming the array in place. There exists some functions to deal with dates and logging. &#xA;&#xA;Test harness&#xA;&#xA;There is a test suite in place that just unit tests the functions to see if the input / output is what is expected. This was quite the thing to setup and maintain actually. Every script is checked with Shellcheck to see if it passes static code analysis. &#xA;&#xA;Open Source&#xA;&#xA;It is open source and the repository is located over here. There are some releases now there but they are haphazard at best. &#xA;&#xA;Future&#xA;&#xA;The future will contain that there will be modules for text, binary, files, network and processes and some more shells. Things like file navigation, file creation for example will all be there. &#xA;&#xA;#code #bash]]&gt;</description>
      <content:encoded><![CDATA[<p>I am currently working on and off on a side project and I named it <em>crucible</em>. It is to do with Shell scripts and I will explain briefly what it does and how. </p>

<h2 id="why-crucible" id="why-crucible">Why crucible?</h2>

<p>So the idea was to first name it <em>anvil</em> or <em>ansible</em> but those two names already exist in the DevOps world as other tools. So then I came up with the idea of a framework that can mould things and then you pour it like from a crucible into whatever shape you chose to make and replicate the scripts completely. In essence I wanted to make a <strong>virtualenv</strong> for shell scripts.</p>

<p>The obvious question is <strong>why</strong> do I wanted to make this. So the reason was mainly to have a nice framework for repeatable and quickly made shell scripts. All those manipulations that you might forget over time and only occasionally need. Like arrays in Bash, or date times, or navigation. There exist a collection of Bash functions but it was not nearly as nicely structured and you had to manually <code>source</code> them.</p>

<p>In addition to this all, I just wanted to see how far I can take one language that is designed to do a very limited set of things. See how far I can take this limited set and make it do things that are normal in other programming languages.</p>

<h2 id="structure" id="structure">Structure</h2>

<p>The structure of the side project is that for each of the shells I want to target:</p>
<ul><li>Bash</li>
<li>Fish</li>
<li>ksh</li>
<li>csh</li>
<li>zsh</li></ul>

<p>I will have written functions that you can <em>require</em>. The entrypoint of the main shell script is a file called <code>.mould</code> . It contains the <code>require</code> function logic. Basically it will download the requirements and source them into your current script.</p>

<p>Then when you are done you call the <code>pour</code> command and it will produce a tarball that will hold the full script with dependencies so you can run it anywhere and everywhere.</p>

<h2 id="example-functions" id="example-functions">Example functions</h2>

<p>For example I made some functions pertaining to dealing with arrays in the shell. There even exists a <code>map</code> functionality that applies a function to every element of the array and thereby transforming the array in place. There exists some functions to deal with <code>dates</code> and <code>logging</code>.</p>

<h2 id="test-harness" id="test-harness">Test harness</h2>

<p>There is a test suite in place that just unit tests the functions to see if the input / output is what is expected. This was quite the thing to setup and maintain actually. Every script is checked with Shellcheck to see if it passes static code analysis.</p>

<h2 id="open-source" id="open-source">Open Source</h2>

<p>It is open source and the repository is located over <a href="https://github.com/StealthyCoder/crucible" rel="nofollow">here</a>. There are some releases now there but they are haphazard at best.</p>

<h2 id="future" id="future">Future</h2>

<p>The future will contain that there will be modules for text, binary, files, network and processes and some more shells. Things like file navigation, file creation for example will all be there.</p>

<p><a href="https://stealthycoder.writeas.com/tag:code" class="hashtag" rel="nofollow"><span>#</span><span class="p-category">code</span></a> <a href="https://stealthycoder.writeas.com/tag:bash" class="hashtag" rel="nofollow"><span>#</span><span class="p-category">bash</span></a></p>
]]></content:encoded>
      <guid>https://stealthycoder.writeas.com/crucible</guid>
      <pubDate>Mon, 27 Jul 2020 20:39:04 +0000</pubDate>
    </item>
    <item>
      <title>Crucible - In Depth</title>
      <link>https://stealthycoder.writeas.com/crucible-in-depth?pk_campaign=rss-feed</link>
      <description>&lt;![CDATA[In the previous post I briefly highlighted my side project. This article will do a little more in depth. !--more--&#xA;&#xA;Getting started&#xA;&#xA;To get started and use it go download the binary and save it somewhere in your PATH in your favourite shell. Then start up your terminal with the shell in question. Navigate to a new path, in our case ~/projects/crucible-example. Within that directory run crucible init. The script will ask two questions. What will be the name of the project and what will the name of the main file be. Project will be Tutorial and the main file will be run.sh. &#xA;Then your directory will look a bit like this:&#xA;~/projects/crucible-example&#xA; |&#xA;  -- .crucible&#xA;  -- .mould&#xA;  -- run.sh&#xA;The contents of .crucible is :&#xA;workingdir=~/projects/crucible-example&#xA;shareddir=~/.local/share/crucible/4e800f0bd0ef69a050bbcae2e0f10c58d058920ce6a686441cfc07011ad7dd16&#xA;version=0.2.6&#xA;location=v0.2.6&#xA;projectname=Tutorial&#xA;mainfile=run.sh&#xA;author=StealthyCoder&#xA;created=1595939715&#xA;&#xA;The shareddir is a place that will follow the XDG conventions if they are set in place and it will house the modules that will be downloaded (required) later on. This will be sectioned off and versioned so you can work on multiple projects without worrying about clashes in versions. &#xA;&#xA;Then .mould will contain the logic of the require function. &#xA;&#xA;Simple example&#xA;&#xA;In our case let us add some logic to the run.sh file. If you open it up you see the following:&#xA;!/usr/bin/env bash&#xA;&#xA;source .mould&#xA;&#xA;This is the start. We shall add the following code to it making it look as follows:&#xA;!/usr/bin/env bash&#xA;&#xA;source .mould&#xA;require arrays/arrays&#xA;require logging/logging&#xA;&#xA;arrays.transformintoarray &#34;a&#34;&#xA;arrays.addall a 1 2 3 4&#xA;&#xA;function multiplyby2 {&#xA;    local result&#xA;    result=&#34;$(( $1 * 2))&#34;&#xA;    echo &#34;$result&#34;&#xA;}&#xA;&#xA;arrays.map a multiplyby2&#xA;&#xA;function simplelog {&#xA;    logging.info &#34;The value is: $1&#34;&#xA;}&#xA;&#xA;arrays.foreach a simplelog&#xA;&#xA;Explanation of the code&#xA;&#xA;require&#xA;The two require lines get the modules downloaded to where your shared location is in the .crucible file. &#xA;&#xA;arrays.transform\into\array&#xA;This line will create a global variable with the name you give it and make it be an array.&#xA;&#xA;arrays.add\_all&#xA;This line will add to the newly created array all the values after the array name. The first position is the name of the array and there are checks and validators that do in fact check if the variable is an array or not.&#xA;&#xA;arrays.map&#xA;The function declaration above it is just there to have a function that will get an input and return that multiplied by 2. The arrays.map takes an array and then the name of a function to be applied to each element. It will check if the arguments are indeed an array and a function. The result of the function will be stored at that position in the array. In our case all numbers will be doubled.&#xA;&#xA;arrays.foreach&#xA;The function declaration above it is just there to have a simple logging function that states &#34;The value is: &#34; with the value given to it. This does not change the array in place however. &#xA;&#xA;Getting a tarball&#xA;&#xA;So this script is nice but it is not distributional, yet. Running crucible pour will get us a tarball with everything correctly in it.  The name of the tarball is the name of the project. In this case Tutorial.tar.gz . &#xA;Within are two files: .lib and run.sh. The .lib file contains all the functions needed and the run.sh just has the require lines removed and the source .mould turned into source .lib. &#xA;&#xA;Improvements&#xA;&#xA;The improvements I want to make on the pour command is that it applies so called tree shaking. Meaning it will only contain what is actually called in from within the script for example, but also make it so it does not have the functions double declared as is the case now. &#xA;&#xA;#code #bash]]&gt;</description>
      <content:encoded><![CDATA[<p>In the <a href="https://stealthycoder.writeas.com/crucible" rel="nofollow">previous</a> post I briefly highlighted my side project. This article will do a little more in depth. </p>

<h1 id="getting-started" id="getting-started">Getting started</h1>

<p>To get started and use it go <a href="https://github.com/StealthyCoder/crucible/releases/download/v0.2.6/crucible" rel="nofollow">download the binary</a> and save it somewhere in your <code>PATH</code> in your favourite shell. Then start up your terminal with the shell in question. Navigate to a new path, in our case <code>~/projects/crucible-example</code>. Within that directory run <code>crucible init</code>. The script will ask two questions. What will be the name of the project and what will the name of the main file be. Project will be <strong>Tutorial</strong> and the main file will be <strong>run.sh</strong>.
Then your directory will look a bit like this:</p>

<pre><code>~/projects/crucible-example
 |
  -- .crucible
  -- .mould
  -- run.sh
</code></pre>

<p>The contents of <em>.crucible</em> is :</p>

<pre><code class="language-id=4e800f0bd0ef69a050bbcae2e0f10c58d058920ce6a686441cfc07011ad7dd16">working_dir=~/projects/crucible-example
shared_dir=~/.local/share/crucible/4e800f0bd0ef69a050bbcae2e0f10c58d058920ce6a686441cfc07011ad7dd16
version=0.2.6
location=v0.2.6
project_name=Tutorial
main_file=run.sh
author=StealthyCoder
created=1595939715
</code></pre>

<p>The <code>shared_dir</code> is a place that will follow the <code>XDG</code> conventions if they are set in place and it will house the modules that will be downloaded (required) later on. This will be sectioned off and versioned so you can work on multiple projects without worrying about clashes in versions.</p>

<p>Then <em>.mould</em> will contain the logic of the <strong>require</strong> function.</p>

<h1 id="simple-example" id="simple-example">Simple example</h1>

<p>In our case let us add some logic to the <code>run.sh</code> file. If you open it up you see the following:</p>

<pre><code class="language-bash">#!/usr/bin/env bash

source .mould
</code></pre>

<p>This is the start. We shall add the following code to it making it look as follows:</p>

<pre><code class="language-bash">#!/usr/bin/env bash

source .mould
require arrays/arrays
require logging/logging

arrays.transform_into_array &#34;a&#34;
arrays.add_all a 1 2 3 4

function multiply_by_2 {
    local result
    result=&#34;$(( $1 * 2))&#34;
    echo &#34;$result&#34;
}

arrays.map a multiply_by_2

function simple_log {
    logging.info &#34;The value is: $1&#34;
}

arrays.foreach a simple_log
</code></pre>

<h1 id="explanation-of-the-code" id="explanation-of-the-code">Explanation of the code</h1>

<h3 id="require" id="require">require</h3>

<p>The two require lines get the modules downloaded to where your shared location is in the .crucible file.</p>

<h3 id="arrays-transform-into-array" id="arrays-transform-into-array">arrays.transform_into_array</h3>

<p>This line will create a <strong>global</strong> variable with the name you give it and make it be an array.</p>

<h3 id="arrays-add-all" id="arrays-add-all">arrays.add_all</h3>

<p>This line will add to the newly created array all the values after the array name. The first position is the name of the array and there are checks and validators that do in fact check if the variable is an array or not.</p>

<h3 id="arrays-map" id="arrays-map">arrays.map</h3>

<p>The function declaration above it is just there to have a function that will get an input and return that multiplied by 2. The <code>arrays.map</code> takes an array and then the name of a function to be applied to each element. It will check if the arguments are indeed an array and a function. The result of the function will be stored at that position in the array. In our case all numbers will be doubled.</p>

<h3 id="arrays-foreach" id="arrays-foreach">arrays.foreach</h3>

<p>The function declaration above it is just there to have a simple logging function that states <code>&#34;The value is: &#34;</code> with the value given to it. This does not change the array in place however.</p>

<h1 id="getting-a-tarball" id="getting-a-tarball">Getting a tarball</h1>

<p>So this script is nice but it is not distributional, yet. Running <code>crucible pour</code> will get us a tarball with everything correctly in it.  The name of the tarball is the name of the project. In this case <code>Tutorial.tar.gz</code> .
Within are two files: <code>.lib</code> and <code>run.sh</code>. The <code>.lib</code> file contains all the functions needed and the <code>run.sh</code> just has the <code>require</code> lines removed and the <code>source .mould</code> turned into <code>source .lib</code>.</p>

<h1 id="improvements" id="improvements">Improvements</h1>

<p>The improvements I want to make on the <code>pour</code> command is that it applies so called tree shaking. Meaning it will only contain what is actually called in from within the script for example, but also make it so it does not have the functions double declared as is the case now.</p>

<p><a href="https://stealthycoder.writeas.com/tag:code" class="hashtag" rel="nofollow"><span>#</span><span class="p-category">code</span></a> <a href="https://stealthycoder.writeas.com/tag:bash" class="hashtag" rel="nofollow"><span>#</span><span class="p-category">bash</span></a></p>
]]></content:encoded>
      <guid>https://stealthycoder.writeas.com/crucible-in-depth</guid>
      <pubDate>Tue, 28 Jul 2020 12:35:54 +0000</pubDate>
    </item>
    <item>
      <title>Crucible - The Future</title>
      <link>https://stealthycoder.writeas.com/crucible-the-future?pk_campaign=rss-feed</link>
      <description>&lt;![CDATA[So these last few days I have been working more on this project. I can actually say it brings me great joy to do this project. It is the combination of tight restrictions that allows my creativity to flow and see just how far we can take this concept and library. !--more--&#xA;&#xA;Cache&#xA;&#xA;I want to implement a caching mechanism for both in-memory and file based cache. The in-memory will just be an associative array with some functionalities in there. The file based one will have the associative array be declared and written to a temp file. It will feature timer based expiry component that checks if it should be evicted. Auto fetching a cache maybe, if it is used when consuming an API. &#xA;&#xA;This all can be built on top of the just completed maps module. &#xA;&#xA;Classes&#xA;&#xA;I want to make a module for classes. They will not really be classes but sort of declared variables and a list of class definitions and class instances. However I think it will be quite fun and funny to see this in action. It will also contain a method called ctor which will instantiate things, then you can always just put down:&#xA;class_instance.a=1&#xA;Like in Python and now it will have that property. &#xA;&#xA;HTTP framework&#xA;&#xA;It would be fun to make a http module that will be able to make requests. It would make get requests with wget maybe but actually send POST requests with the use of nc. &#xA;&#xA;Web framework&#xA;&#xA;To take it a little further what I want to try and make is a Unix domain socket and have it hook into a live running Bash process that will read it and execute controllers based on the routes. It should make use of the processes, io , http and class modules. &#xA;&#xA;#code #bash]]&gt;</description>
      <content:encoded><![CDATA[<p>So these last few days I have been working more on this project. I can actually say it brings me great joy to do this project. It is the combination of tight restrictions that allows my creativity to flow and see just how far we can take this concept and library. </p>

<h1 id="cache" id="cache">Cache</h1>

<p>I want to implement a caching mechanism for both in-memory and file based cache. The in-memory will just be an associative array with some functionalities in there. The file based one will have the associative array be declared and written to a temp file. It will feature timer based expiry component that checks if it should be evicted. Auto fetching a cache maybe, if it is used when consuming an API.</p>

<p>This all can be built on top of the just completed <code>maps</code> module.</p>

<h1 id="classes" id="classes">Classes</h1>

<p>I want to make a module for <em>classes</em>. They will not really be classes but sort of declared variables and a list of class definitions and class instances. However I think it will be quite fun and funny to see this in action. It will also contain a method called <code>ctor</code> which will instantiate things, then you can always just put down:</p>

<pre><code class="language-bash">class_instance.a=1
</code></pre>

<p>Like in Python and now it will have that property.</p>

<h1 id="http-framework" id="http-framework">HTTP framework</h1>

<p>It would be fun to make a <code>http</code> module that will be able to make requests. It would make get requests with <code>wget</code> maybe but actually send POST requests with the use of <code>nc</code>.</p>

<h1 id="web-framework" id="web-framework">Web framework</h1>

<p>To take it a little further what I want to try and make is a Unix domain socket and have it hook into a live running Bash process that will read it and execute controllers based on the routes. It should make use of the <code>processes</code>, <code>io</code> , <code>http</code> and <code>class</code> modules.</p>

<p><a href="https://stealthycoder.writeas.com/tag:code" class="hashtag" rel="nofollow"><span>#</span><span class="p-category">code</span></a> <a href="https://stealthycoder.writeas.com/tag:bash" class="hashtag" rel="nofollow"><span>#</span><span class="p-category">bash</span></a></p>
]]></content:encoded>
      <guid>https://stealthycoder.writeas.com/crucible-the-future</guid>
      <pubDate>Wed, 29 Jul 2020 16:11:05 +0000</pubDate>
    </item>
  </channel>
</rss>