Shebang, Hebang, and Webang lines. Execute any type of file from the terminal
Tags: cli, productivity, hack, terminal
Published: 2021-01-10 16:15:14

This article will explain how to execute a file from the terminal without having to type out long commands and arguments every time. Most people working on Unix and Linux based OS will know what a shebang `#!` line is, this article will explain why there should be more type of bang lines and how to create them.

## Table of content

- [How operating system identifies executable](#how-operating-system-identifies-executable)
- [Shebang](#shebang)
- [Hebang and Webang](#hebang-and-webang)
- [Why more type of bang lines](#why-more-type-of-bang-lines)
- [Writing custom bang lines program](#writing-custom-bang-lines-program)
  - [Powershell](#powershell)
  - [Bash](#bash)

## How operating system identifies executable

There are various ways by which an operating system identifies a file as an executable. On platforms like Unix, Linux, and Mac the executable are mostly identified by its magic number which consists of byte string while on windows any file ending with **.exe**, **.cmd** or **.com** is identified as an executable, and for other types of file, it relies on the file association in the registry to identify what program to execute the file with. 

An example of file association on windows is the .txt extension associated with any text editor you selected in the Open with dialog. Or the .html extension which is associated with Edge by default until you change the default executable to associate with the extension and the .py files associated with Python IDLE on windows.

The magic numbers for some binary like png, elf, pdf can be seen in this [Wikipedia list](https://en.wikipedia.org/wiki/Magic_number_(programming)#Magic_numbers_in_files). *The magic number can also be used to detect a file MIME type properly instead of relying on the file extension.*

## Shebang

According to [Wikipedia](https://en.wikipedia.org/wiki/Shebang_(Unix)), "In computing, a shebang is the character sequence consisting of the characters number sign and exclamation mark (#!) at the beginning of a script. It is also called sha-bang, hashbang, pound-bang, or hash-pling".

From the explanation of magic number in the last section, shebang can simply be explained as a human-readable version of the [magic number](http://en.wikipedia.org/wiki/Magic_number_(programming)#Magic_numbers_in_files), it is used by the os procedures for executing a file to determine whether the file should be executed directly or as a binary. 

When the shebang line is specified at the top of the file the os procedures will execute the command in the shebang line without executing the file itself. The procedure will then pass the absolute path to the file to the binary specified on the shebang line.

Example of a shebang line below:

```python
#!/usr/bin/env python3

print("Hey through shebang")
```

Executing the file from the terminal with the command `./test.py` and `python3 test.py` will output the same text.

## Hebang and Webang

From the explanation of the shebang line above it has a huge limitation which is it cannot be used in source code or files that do not use `#` as a comment or has a special use-case for the character `#`, enters hebang, and webang lines. 

I had the idea for hebang when I need to run unit tests for my C projects and every time I had to go to the terminal to run long commands. Using shebang is not possible in C as the `#` is used for macro preprocessing, since `//` is used for comments I decided to have another type of shebang but using // instead of #. After a while when I tried to run a C source that targets C90 and below with my custom hebang command I get the error `C++ style comments are not allowed in ISO C90` and according to the C90 standard // is not a valid comment the only valid comment is `/* */` so I had to add another type of bang line which I call webang.

![hebang_error](https://dev-to-uploads.s3.amazonaws.com/i/axwckkemic1813pee1bn.png)
  

These two new terms are my attempt to provide an alternative solution to shebang limitation, hebang, and webang lines are to bring the same functionality of shebang and more into other files that do not use `#` as a comment. The hebang uses `//!` as its prefix and webang use `/*!`. 

The example below defines a hebang and webang line for a C file.

Hebang line
```c
//!gcc {0} -I. -I../../include/ -o out; ./out

#include <stdio.h>

int main(int agvc, char **argv)
{
    printf("Hello through hebang and webang!!!\n");
}
```

Webang line
```c
/*!gcc {0} -I. -I../../include/ -o out; ./out */

#include <stdio.h>

int main(int agvc, char **argv)
{
    printf("Hello through hebang and webang!!!\n");
}
```

## Why more type of bang lines

Normally shebang will work fine for files using `#` as a comment and executed with an interpreter, but for a compiled language like C, Java, Rust that needs to be compiled, sometimes linked before the generated binary can be executed shebang might not work as it only appends the file path at the end of the bang string. 

With a custom shebang, hebang, and webang script multiple commands can be written in the bang line for any type of file, various steps like compilation, linking, and execution can be executed with just one bang line.

## Writing custom bang lines scripts

The basics for writing your own bang line command are:

- Read the first line of the file
- Check the first two chars in the first line,
   - if it equals `#!` that a shebang line
   - if it equals `//` and the next char is `!` that a hebang line
   - if it equals `/*` and the next char is `!` that a webang line
- If the first two chars do not match above send the file to the os for execution using the appropriate logic of any language you implementing in.
- If it matches any of the bang line strip the bang prefix and in case of webang remove the comment suffix `*/`
- Then execute the remaining string with the absolute file path appended to the string from the bang line.
- But in my case, I did not append the file path to the bang command instead I allow the use of string format so I can accept the file at any part of the bang string. e.g. `gcc {0} -o out; ./out` my command replaces {0} with the path to the file been executed and appends the remaining arguments from the terminal to the expanded string, therefore the command above will be expanded into `gcc test_bang.c -o out; ./out`.

Give your command/script any name and use it to execute your files. By following the command above you can also use the command/script to execute any type of file and not the ones with bang lines only.

For the example above, My command name is `$` to make sure it not intrusive and not noticeable in the terminal.

```
$ test_bang.c --help
```

The bang line in the file test_bang.c will expand to:

```
gcc test_bang.c -I. -I../../include/ -o out; ./out --help
```

Another example of executing a Javascript source (test_bang.js) using a hebang line

```js
//*!node {0}

console.log("Hello " + process.argv[2]);
```

```
> $ test_bang.js dev.to
> Hello dev.to
```

My first attempt at creating the bang line script is using Batch file as part of the [Cronux](https://github.com/Thecarisma/Cronux) collection, I later rewrite the commands in the collection using Powershell for sanity. I had to write the bash version of the script as I don't have so much time to port Cronux to Unix, Linux, and Mac.

You can save any of the sources below as `$` and start using hebang and shebang in your files, e.g. if you save as bang.ps1 or bang.sh

```
bang python.py
bang test_bang.c 
```

### Powershell

{% gist https://gist.github.com/Thecarisma/518b1bcc80a08191b8fd5a4e88ad9f21 %}

### Bash

{% gist https://gist.github.com/Thecarisma/6783529868b453fcbd430a46c8e895fc %}

I hope this article helps maximize your productivity.