#shellscripting — Public Fediverse posts
Live and recent posts from across the Fediverse tagged #shellscripting, aggregated by home.social.
-
MIMEcroft.sh: a 3D game written in bash
https://gmatht.github.io/j.cmd/www/MIMEcroft.html is a parody of every 3D game ever, that lovingly pokes fun of bash's reputation for poor performance - by subverting it. MIMEcroft.sh is written entirely in Bash. The game logic, GPU shaders, even the sounds and textures are procedurally generated with bash commands.
One may wonder how MIMEcroft.sh pumps out 90fps at 4K given bash's reputation for poor performance. Indeed, the official GNU bash reference interpreter is poorly optimised compared to languages more commonly used for game development like C++. However, if your web-browser has a GUI it almost certainly also has a highly optimised JavaScript interpreter.
The online JavaScript Commandline OS (j.cmd) did not port the reference implementation of bash and coreutils. Instead it takes the abstract language they describe. This language is translated into JavaScript, which a modern runtime can often reduce to machine code, resulting in performance over a thousand times faster than the original bash.
For a concrete if somewhat contrived example say you are interested in finding numbers with 1337 squares, and use the one-liner:
for i in `seq 1 10000`;do if echo $((i*i)) | grep 1337 > /dev/null;then echo $i;fi;done
In the official bash interpreter, this may take a minute. However, j.cmd implements it by first transpiling it into:
for (let i = 1; i <= 10000; i++) {
if (String(i * i).includes("1337")) {
process.stdout.write(i + "\n");
}
}
sh2.lastExit = 0;Then it is all over in the blink of an eye.
One might well argue that this is not a real bash game since it has to transpile to JS before being run. A stronger argument could be made that C++ games are not real C++ games. A C++ game also has to be compiled. In most "C++" games the developer doesn't even give you the C++ source, you only ever get the compiled machine code. MIMEcroft.sh is stored and distributed as bash. You can edit it as bash (try e.g. `vi /bin/mimecroft.sh` in j.cmd, changing `cys=0.900` to `cys=3.900` and playing the game again). The current version of j.cmd doesn't even cache the transpiled JS version of the game.
____________
It is important to note that j.cmd is experimental and still has many bugs. One little way it is more robust than the traditional bash implementations is that traditional shells tend to break if they source a file that isn’t in their own special format. On the other hand, j.cmd sees different shell formats as just different ways of saying the same thing. It will quite happily run:for f in /home/examples/source.{bat,c,fish,sh,zsh}; do . $f; done
Sourcing C files is still a work in progress in j.cmd. I recently added support for passing linked lists and pointers to bash variables/functions into sourced C functions, and cd'ing around C pointer structure.
#bash #sh #shellScripting #Linux #games #3D #Javascript #GLSL -
MIMEcroft.sh: a 3D game written in bash
https://gmatht.github.io/j.cmd/www/MIMEcroft.html is a parody of every 3D game ever, that lovingly pokes fun of bash's reputation for poor performance - by subverting it. MIMEcroft.sh is written entirely in Bash. The game logic, GPU shaders, even the sounds and textures are procedurally generated with bash commands.
One may wonder how MIMEcroft.sh pumps out 90fps at 4K given bash's reputation for poor performance. Indeed, the official GNU bash reference interpreter is poorly optimised compared to languages more commonly used for game development like C++. However, if your web-browser has a GUI it almost certainly also has a highly optimised JavaScript interpreter.
The online JavaScript Commandline OS (j.cmd) did not port the reference implementation of bash and coreutils. Instead it takes the abstract language they describe. This language is translated into JavaScript, which a modern runtime can often reduce to machine code, resulting in performance over a thousand times faster than the original bash.
For a concrete if somewhat contrived example say you are interested in finding numbers with 1337 squares, and use the one-liner:
for i in `seq 1 10000`;do if echo $((i*i)) | grep 1337 > /dev/null;then echo $i;fi;done
In the official bash interpreter, this may take a minute. However, j.cmd implements it by first transpiling it into:
for (let i = 1; i <= 10000; i++) {
if (String(i * i).includes("1337")) {
process.stdout.write(i + "\n");
}
}
sh2.lastExit = 0;Then it is all over in the blink of an eye.
One might well argue that this is not a real bash game since it has to transpile to JS before being run. A stronger argument could be made that C++ games are not real C++ games. A C++ game also has to be compiled. In most "C++" games the developer doesn't even give you the C++ source, you only ever get the compiled machine code. MIMEcroft.sh is stored and distributed as bash. You can edit it as bash (try e.g. `vi /bin/mimecroft.sh` in j.cmd, changing `cys=0.900` to `cys=3.900` and playing the game again). The current version of j.cmd doesn't even cache the transpiled JS version of the game.
____________
It is important to note that j.cmd is experimental and still has many bugs. One little way it is more robust than the traditional bash implementations is that traditional shells tend to break if they source a file that isn’t in their own special format. On the other hand, j.cmd sees different shell formats as just different ways of saying the same thing. It will quite happily run:for f in /home/examples/source.{bat,c,fish,sh,zsh}; do . $f; done
Sourcing C files is still a work in progress in j.cmd. I recently added support for passing linked lists and pointers to bash variables/functions into sourced C functions, and cd'ing around C pointer structure.
#bash #sh #shellScripting #Linux #games #3D #Javascript #GLSL -
MIMEcroft.sh: a 3D game written in bash
https://gmatht.github.io/j.cmd/www/MIMEcroft.html is a parody of every 3D game ever, that lovingly pokes fun of bash's reputation for poor performance - by subverting it. MIMEcroft.sh is written entirely in Bash. The game logic, GPU shaders, even the sounds and textures are procedurally generated with bash commands.
One may wonder how MIMEcroft.sh pumps out 90fps at 4K given bash's reputation for poor performance. Indeed, the official GNU bash reference interpreter is poorly optimised compared to languages more commonly used for game development like C++. However, if your web-browser has a GUI it almost certainly also has a highly optimised JavaScript interpreter.
The online JavaScript Commandline OS (j.cmd) did not port the reference implementation of bash and coreutils. Instead it takes the abstract language they describe. This language is translated into JavaScript, which a modern runtime can often reduce to machine code, resulting in performance over a thousand times faster than the original bash.
For a concrete if somewhat contrived example say you are interested in finding numbers with 1337 squares, and use the one-liner:
for i in `seq 1 10000`;do if echo $((i*i)) | grep 1337 > /dev/null;then echo $i;fi;done
In the official bash interpreter, this may take a minute. However, j.cmd implements it by first transpiling it into:
for (let i = 1; i <= 10000; i++) {
if (String(i * i).includes("1337")) {
process.stdout.write(i + "\n");
}
}
sh2.lastExit = 0;Then it is all over in the blink of an eye.
One might well argue that this is not a real bash game since it has to transpile to JS before being run. A stronger argument could be made that C++ games are not real C++ games. A C++ game also has to be compiled. In most "C++" games the developer doesn't even give you the C++ source, you only ever get the compiled machine code. MIMEcroft.sh is stored and distributed as bash. You can edit it as bash (try e.g. `vi /bin/mimecroft.sh` in j.cmd, changing `cys=0.900` to `cys=3.900` and playing the game again). The current version of j.cmd doesn't even cache the transpiled JS version of the game.
____________
It is important to note that j.cmd is experimental and still has many bugs. One little way it is more robust than the traditional bash implementations is that traditional shells tend to break if they source a file that isn’t in their own special format. On the other hand, j.cmd sees different shell formats as just different ways of saying the same thing. It will quite happily run:for f in /home/examples/source.{bat,c,fish,sh,zsh}; do . $f; done
Sourcing C files is still a work in progress in j.cmd. I recently added support for passing linked lists and pointers to bash variables/functions into sourced C functions, and cd'ing around C pointer structure.
#bash #sh #shellScripting #Linux #games #3D #Javascript #GLSL -
MIMEcroft.sh: a 3D game written in bash
https://gmatht.github.io/j.cmd/www/MIMEcroft.html is a parody of every 3D game ever, that lovingly pokes fun of bash's reputation for poor performance - by subverting it. MIMEcroft.sh is written entirely in Bash. The game logic, GPU shaders, even the sounds and textures are procedurally generated with bash commands.
One may wonder how MIMEcroft.sh pumps out 90fps at 4K given bash's reputation for poor performance. Indeed, the official GNU bash reference interpreter is poorly optimised compared to languages more commonly used for game development like C++. However, if your web-browser has a GUI it almost certainly also has a highly optimised JavaScript interpreter.
The online JavaScript Commandline OS (j.cmd) did not port the reference implementation of bash and coreutils. Instead it takes the abstract language they describe. This language is translated into JavaScript, which a modern runtime can often reduce to machine code, resulting in performance over a thousand times faster than the original bash.
For a concrete if somewhat contrived example say you are interested in finding numbers with 1337 squares, and use the one-liner:
for i in `seq 1 10000`;do if echo $((i*i)) | grep 1337 > /dev/null;then echo $i;fi;done
In the official bash interpreter, this may take a minute. However, j.cmd implements it by first transpiling it into:
for (let i = 1; i <= 10000; i++) {
if (String(i * i).includes("1337")) {
process.stdout.write(i + "\n");
}
}
sh2.lastExit = 0;Then it is all over in the blink of an eye.
One might well argue that this is not a real bash game since it has to transpile to JS before being run. A stronger argument could be made that C++ games are not real C++ games. A C++ game also has to be compiled. In most "C++" games the developer doesn't even give you the C++ source, you only ever get the compiled machine code. MIMEcroft.sh is stored and distributed as bash. You can edit it as bash (try e.g. `vi /bin/mimecroft.sh` in j.cmd, changing `cys=0.900` to `cys=3.900` and playing the game again). The current version of j.cmd doesn't even cache the transpiled JS version of the game.
____________
It is important to note that j.cmd is experimental and still has many bugs. One little way it is more robust than the traditional bash implementations is that traditional shells tend to break if they source a file that isn’t in their own special format. On the other hand, j.cmd sees different shell formats as just different ways of saying the same thing. It will quite happily run:for f in /home/examples/source.{bat,c,fish,sh,zsh}; do . $f; done
Sourcing C files is still a work in progress in j.cmd. I recently added support for passing linked lists and pointers to bash variables/functions into sourced C functions, and cd'ing around C pointer structure.
#bash #sh #shellScripting #Linux #games #3D #Javascript #GLSL -
MIMEcroft.sh: a 3D game written in bash
https://gmatht.github.io/j.cmd/www/MIMEcroft.html is a parody of every 3D game ever, that lovingly pokes fun of bash's reputation for poor performance - by subverting it. MIMEcroft.sh is written entirely in Bash. The game logic, GPU shaders, even the sounds and textures are procedurally generated with bash commands.
One may wonder how MIMEcroft.sh pumps out 90fps at 4K given bash's reputation for poor performance. Indeed, the official GNU bash reference interpreter is poorly optimised compared to languages more commonly used for game development like C++. However, if your web-browser has a GUI it almost certainly also has a highly optimised JavaScript interpreter.
The online JavaScript Commandline OS (j.cmd) did not port the reference implementation of bash and coreutils. Instead it takes the abstract language they describe. This language is translated into JavaScript, which a modern runtime can often reduce to machine code, resulting in performance over a thousand times faster than the original bash.
For a concrete if somewhat contrived example say you are interested in finding numbers with 1337 squares, and use the one-liner:
for i in `seq 1 10000`;do if echo $((i*i)) | grep 1337 > /dev/null;then echo $i;fi;done
In the official bash interpreter, this may take a minute. However, j.cmd implements it by first transpiling it into:
for (let i = 1; i <= 10000; i++) {
if (String(i * i).includes("1337")) {
process.stdout.write(i + "\n");
}
}
sh2.lastExit = 0;Then it is all over in the blink of an eye.
One might well argue that this is not a real bash game since it has to transpile to JS before being run. A stronger argument could be made that C++ games are not real C++ games. A C++ game also has to be compiled. In most "C++" games the developer doesn't even give you the C++ source, you only ever get the compiled machine code. MIMEcroft.sh is stored and distributed as bash. You can edit it as bash (try e.g. `vi /bin/mimecroft.sh` in j.cmd, changing `cys=0.900` to `cys=3.900` and playing the game again). The current version of j.cmd doesn't even cache the transpiled JS version of the game.
____________
It is important to note that j.cmd is experimental and still has many bugs. One little way it is more robust than the traditional bash implementations is that traditional shells tend to break if they source a file that isn’t in their own special format. On the other hand, j.cmd sees different shell formats as just different ways of saying the same thing. It will quite happily run:for f in /home/examples/source.{bat,c,fish,sh,zsh}; do . $f; done
Sourcing C files is still a work in progress in j.cmd. I recently added support for passing linked lists and pointers to bash variables/functions into sourced C functions, and cd'ing around C pointer structure.
#bash #sh #shellScripting #Linux #games #3D #Javascript #GLSL -
Need to create a bunch of files or directories on Linux each with a new number?
🪄 A shell like bash can expand what is within the curly braces. You can even use steps en prefix with zeroes, so all names are equally long and easy to sort.
💡 Good to know: not all shells support this, so be careful in scripts.
-
Need to create a bunch of files or directories on Linux each with a new number?
🪄 A shell like bash can expand what is within the curly braces. You can even use steps en prefix with zeroes, so all names are equally long and easy to sort.
💡 Good to know: not all shells support this, so be careful in scripts.
-
Need to create a bunch of files or directories on Linux each with a new number?
🪄 A shell like bash can expand what is within the curly braces. You can even use steps en prefix with zeroes, so all names are equally long and easy to sort.
💡 Good to know: not all shells support this, so be careful in scripts.
-
Need to create a bunch of files or directories on Linux each with a new number?
🪄 A shell like bash can expand what is within the curly braces. You can even use steps en prefix with zeroes, so all names are equally long and easy to sort.
💡 Good to know: not all shells support this, so be careful in scripts.
-
Need to create a bunch of files or directories on Linux each with a new number?
🪄 A shell like bash can expand what is within the curly braces. You can even use steps en prefix with zeroes, so all names are equally long and easy to sort.
💡 Good to know: not all shells support this, so be careful in scripts.
-
If someone wonders about this:
: ${E:?This is an error message.}It is a POSIX feature for showing errors and exiting if a variable has no content.
It has the benefit of printing the line number.It uses : so that ${} can run on its own. The E:? checks if a variable E has content, if not it Prints the error message and exits the current shell.
The reason why I use E is because it shows like an error, but you can use ERROR too if that is more clear (and you are certain that variable is empty.
#shellScripting #linux #bsd -
If someone wonders about this:
: ${E:?This is an error message.}It is a POSIX feature for showing errors and exiting if a variable has no content.
It has the benefit of printing the line number.It uses : so that ${} can run on its own. The E:? checks if a variable E has content, if not it Prints the error message and exits the current shell.
The reason why I use E is because it shows like an error, but you can use ERROR too if that is more clear (and you are certain that variable is empty.
#shellScripting #linux #bsd -
If someone wonders about this:
: ${E:?This is an error message.}It is a POSIX feature for showing errors and exiting if a variable has no content.
It has the benefit of printing the line number.It uses : so that ${} can run on its own. The E:? checks if a variable E has content, if not it Prints the error message and exits the current shell.
The reason why I use E is because it shows like an error, but you can use ERROR too if that is more clear (and you are certain that variable is empty.
#shellScripting #linux #bsd -
If someone wonders about this:
: ${E:?This is an error message.}It is a POSIX feature for showing errors and exiting if a variable has no content.
It has the benefit of printing the line number.It uses : so that ${} can run on its own. The E:? checks if a variable E has content, if not it Prints the error message and exits the current shell.
The reason why I use E is because it shows like an error, but you can use ERROR too if that is more clear (and you are certain that variable is empty.
#shellScripting #linux #bsd -
If someone wonders about this:
: ${E:?This is an error message.}It is a POSIX feature for showing errors and exiting if a variable has no content.
It has the benefit of printing the line number.It uses : so that ${} can run on its own. The E:? checks if a variable E has content, if not it Prints the error message and exits the current shell.
The reason why I use E is because it shows like an error, but you can use ERROR too if that is more clear (and you are certain that variable is empty.
#shellScripting #linux #bsd -
All my shell scripts start like this:
This section removes all variables, functions and aliases with single letter identifiers:
```
i="A B C D E F G H I J K L M N O P Q R S T U V W X Y Z \
a b c d e f g h i j k l m n o p q r s t u v w x y z"
eval "unset -f $i; unset $i; unalias $i" >/dev/null 2>&1; :
```
This sections prevents this from running on shells that do not support local:
```
(command -v local >/dev/null || exit;F(){ local i=1; };F;[ -z "$i" ] && exit) \
|| : ${E:?"This shell doesn't support local variables. This can't run on it."}
```
The original directory the script was called from:
`OG_PWD=$PWD`This process id:
`PROC_PID=$$`The first command used to execute this script, Eg `bash ./script.sh` would yield 'bash', doing `./script.sh` would yield 'script.sh'.
`PROC_COMM=$(ps -p $$ -o comm=)`The location of this source file:
`SOURCE_FILE=$(readlink -f "$0") || : ${E:?readlink -f "$0" failed}`The directory of the source file, it also `cd`s to it to make sure it exists and to make relative path imports easier.
SOURCE_PATH=$(dirname "$SOURCE_FILE") && cd "$SOURCE_PATH" || : ${E:?Failed cd}The path to the current shell running the script:
`SHELL_PATH=$(x=$(command -v "$PROC_COMM" || command -v sh);readlink -f "$x")` -
All my shell scripts start like this:
This section removes all variables, functions and aliases with single letter identifiers:
```
i="A B C D E F G H I J K L M N O P Q R S T U V W X Y Z \
a b c d e f g h i j k l m n o p q r s t u v w x y z"
eval "unset -f $i; unset $i; unalias $i" >/dev/null 2>&1; :
```
This sections prevents this from running on shells that do not support local:
```
(command -v local >/dev/null || exit;F(){ local i=1; };F;[ -z "$i" ] && exit) \
|| : ${E:?"This shell doesn't support local variables. This can't run on it."}
```
The original directory the script was called from:
`OG_PWD=$PWD`This process id:
`PROC_PID=$$`The first command used to execute this script, Eg `bash ./script.sh` would yield 'bash', doing `./script.sh` would yield 'script.sh'.
`PROC_COMM=$(ps -p $$ -o comm=)`The location of this source file:
`SOURCE_FILE=$(readlink -f "$0") || : ${E:?readlink -f "$0" failed}`The directory of the source file, it also `cd`s to it to make sure it exists and to make relative path imports easier.
SOURCE_PATH=$(dirname "$SOURCE_FILE") && cd "$SOURCE_PATH" || : ${E:?Failed cd}The path to the current shell running the script:
`SHELL_PATH=$(x=$(command -v "$PROC_COMM" || command -v sh);readlink -f "$x")` -
All my shell scripts start like this:
This section removes all variables, functions and aliases with single letter identifiers:
```
i="A B C D E F G H I J K L M N O P Q R S T U V W X Y Z \
a b c d e f g h i j k l m n o p q r s t u v w x y z"
eval "unset -f $i; unset $i; unalias $i" >/dev/null 2>&1; :
```
This sections prevents this from running on shells that do not support local:
```
(command -v local >/dev/null || exit;F(){ local i=1; };F;[ -z "$i" ] && exit) \
|| : ${E:?"This shell doesn't support local variables. This can't run on it."}
```
The original directory the script was called from:
`OG_PWD=$PWD`This process id:
`PROC_PID=$$`The first command used to execute this script, Eg `bash ./script.sh` would yield 'bash', doing `./script.sh` would yield 'script.sh'.
`PROC_COMM=$(ps -p $$ -o comm=)`The location of this source file:
`SOURCE_FILE=$(readlink -f "$0") || : ${E:?readlink -f "$0" failed}`The directory of the source file, it also `cd`s to it to make sure it exists and to make relative path imports easier.
SOURCE_PATH=$(dirname "$SOURCE_FILE") && cd "$SOURCE_PATH" || : ${E:?Failed cd}The path to the current shell running the script:
`SHELL_PATH=$(x=$(command -v "$PROC_COMM" || command -v sh);readlink -f "$x")` -
All my shell scripts start like this:
This section removes all variables, functions and aliases with single letter identifiers:
```
i="A B C D E F G H I J K L M N O P Q R S T U V W X Y Z \
a b c d e f g h i j k l m n o p q r s t u v w x y z"
eval "unset -f $i; unset $i; unalias $i" >/dev/null 2>&1; :
```
This sections prevents this from running on shells that do not support local:
```
(command -v local >/dev/null || exit;F(){ local i=1; };F;[ -z "$i" ] && exit) \
|| : ${E:?"This shell doesn't support local variables. This can't run on it."}
```
The original directory the script was called from:
`OG_PWD=$PWD`This process id:
`PROC_PID=$$`The first command used to execute this script, Eg `bash ./script.sh` would yield 'bash', doing `./script.sh` would yield 'script.sh'.
`PROC_COMM=$(ps -p $$ -o comm=)`The location of this source file:
`SOURCE_FILE=$(readlink -f "$0") || : ${E:?readlink -f "$0" failed}`The directory of the source file, it also `cd`s to it to make sure it exists and to make relative path imports easier.
SOURCE_PATH=$(dirname "$SOURCE_FILE") && cd "$SOURCE_PATH" || : ${E:?Failed cd}The path to the current shell running the script:
`SHELL_PATH=$(x=$(command -v "$PROC_COMM" || command -v sh);readlink -f "$x")` -
All my shell scripts start like this:
This section removes all variables, functions and aliases with single letter identifiers:
```
i="A B C D E F G H I J K L M N O P Q R S T U V W X Y Z \
a b c d e f g h i j k l m n o p q r s t u v w x y z"
eval "unset -f $i; unset $i; unalias $i" >/dev/null 2>&1; :
```
This sections prevents this from running on shells that do not support local:
```
(command -v local >/dev/null || exit;F(){ local i=1; };F;[ -z "$i" ] && exit) \
|| : ${E:?"This shell doesn't support local variables. This can't run on it."}
```
The original directory the script was called from:
`OG_PWD=$PWD`This process id:
`PROC_PID=$$`The first command used to execute this script, Eg `bash ./script.sh` would yield 'bash', doing `./script.sh` would yield 'script.sh'.
`PROC_COMM=$(ps -p $$ -o comm=)`The location of this source file:
`SOURCE_FILE=$(readlink -f "$0") || : ${E:?readlink -f "$0" failed}`The directory of the source file, it also `cd`s to it to make sure it exists and to make relative path imports easier.
SOURCE_PATH=$(dirname "$SOURCE_FILE") && cd "$SOURCE_PATH" || : ${E:?Failed cd}The path to the current shell running the script:
`SHELL_PATH=$(x=$(command -v "$PROC_COMM" || command -v sh);readlink -f "$x")` -
🧰 The awk command is like a Swiss army knife but for data. So if you handle file data now and then, it is worth learning and practice with it.
Awk is great on the command line, but also if you create some shellscript to automate a task 🤖
For example, it can quickly filter out any long (or short) lines of a file.
💡 Good to know: awk is available on most Unix-like systems, but their implementation differs a little bit.
-
🧰 The awk command is like a Swiss army knife but for data. So if you handle file data now and then, it is worth learning and practice with it.
Awk is great on the command line, but also if you create some shellscript to automate a task 🤖
For example, it can quickly filter out any long (or short) lines of a file.
💡 Good to know: awk is available on most Unix-like systems, but their implementation differs a little bit.
-
🧰 The awk command is like a Swiss army knife but for data. So if you handle file data now and then, it is worth learning and practice with it.
Awk is great on the command line, but also if you create some shellscript to automate a task 🤖
For example, it can quickly filter out any long (or short) lines of a file.
💡 Good to know: awk is available on most Unix-like systems, but their implementation differs a little bit.
-
🧰 The awk command is like a Swiss army knife but for data. So if you handle file data now and then, it is worth learning and practice with it.
Awk is great on the command line, but also if you create some shellscript to automate a task 🤖
For example, it can quickly filter out any long (or short) lines of a file.
💡 Good to know: awk is available on most Unix-like systems, but their implementation differs a little bit.
-
🧰 The awk command is like a Swiss army knife but for data. So if you handle file data now and then, it is worth learning and practice with it.
Awk is great on the command line, but also if you create some shellscript to automate a task 🤖
For example, it can quickly filter out any long (or short) lines of a file.
💡 Good to know: awk is available on most Unix-like systems, but their implementation differs a little bit.
-
I have managed a single PS1 that works across most bournelike shells :3
And it prints the red ? when the previous command failed too!
#linux #shellScripting -
I have managed a single PS1 that works across most bournelike shells :3
And it prints the red ? when the previous command failed too!
#linux #shellScripting -
I have managed a single PS1 that works across most bournelike shells :3
And it prints the red ? when the previous command failed too!
#linux #shellScripting -
I have managed a single PS1 that works across most bournelike shells :3
And it prints the red ? when the previous command failed too!
#linux #shellScripting -
I have managed a single PS1 that works across most bournelike shells :3
And it prints the red ? when the previous command failed too!
#linux #shellScripting -
Think I've got enough #ksh implementations installed? XD
rld@Intrepid:~$ pkg info |grep ksh ksh-1.0.10 ksh93u+m is the renewed development of ksh93 based on AT&T ksh93u+m (stable) mksh-59c_3 MirBSD Korn Shell oksh-7.8,1 Portable OpenBSD Korn shell pdksh-5.2.14p2_7 The Public Domain Korn Shell rld@Intrepid:~$#mksh #pdksh #oksh #testing #unix #unixShell #ShellScripting
-
Think I've got enough #ksh implementations installed? XD
rld@Intrepid:~$ pkg info |grep ksh ksh-1.0.10 ksh93u+m is the renewed development of ksh93 based on AT&T ksh93u+m (stable) mksh-59c_3 MirBSD Korn Shell oksh-7.8,1 Portable OpenBSD Korn shell pdksh-5.2.14p2_7 The Public Domain Korn Shell rld@Intrepid:~$#mksh #pdksh #oksh #testing #unix #unixShell #ShellScripting
-
Think I've got enough #ksh implementations installed? XD
rld@Intrepid:~$ pkg info |grep ksh ksh-1.0.10 ksh93u+m is the renewed development of ksh93 based on AT&T ksh93u+m (stable) mksh-59c_3 MirBSD Korn Shell oksh-7.8,1 Portable OpenBSD Korn shell pdksh-5.2.14p2_7 The Public Domain Korn Shell rld@Intrepid:~$#mksh #pdksh #oksh #testing #unix #unixShell #ShellScripting
-
Think I've got enough #ksh implementations installed? XD
rld@Intrepid:~$ pkg info |grep ksh ksh-1.0.10 ksh93u+m is the renewed development of ksh93 based on AT&T ksh93u+m (stable) mksh-59c_3 MirBSD Korn Shell oksh-7.8,1 Portable OpenBSD Korn shell pdksh-5.2.14p2_7 The Public Domain Korn Shell rld@Intrepid:~$#mksh #pdksh #oksh #testing #unix #unixShell #ShellScripting
-
Think I've got enough #ksh implementations installed? XD
rld@Intrepid:~$ pkg info |grep ksh ksh-1.0.10 ksh93u+m is the renewed development of ksh93 based on AT&T ksh93u+m (stable) mksh-59c_3 MirBSD Korn Shell oksh-7.8,1 Portable OpenBSD Korn shell pdksh-5.2.14p2_7 The Public Domain Korn Shell rld@Intrepid:~$#mksh #pdksh #oksh #testing #unix #unixShell #ShellScripting
-
In the #shell #functions I should have written years ago category...
function fedilinktousername { grep -oE 'https?://[^/]+/@[^/ ]+' |sed -E 's|https?://|@|; s|/@|@|; s/(@[^@]*)(@[^@]*)/\2\1/' } function fediusernametolink { grep -oE '(@[^@ ]+){2}' |sed -E 's|(@[^@ ]+)@([^@ ]+)|https://\2/\1|' }rld@Intrepid:~$ clipo https://polymaths.social/@rl_dane/statuses/01KVJCAG6Y4C1KTGBDBECH2778 rld@Intrepid:~$ clipo |fedilinktousername @[email protected] rld@Intrepid:~$ clipo |fedilinktousername |fediusernametolink https://polymaths.social/@rl_dane rld@Intrepid:~$ -
In the #shell #functions I should have written years ago category...
function fedilinktousername { grep -oE 'https?://[^/]+/@[^/ ]+' |sed -E 's|https?://|@|; s|/@|@|; s/(@[^@]*)(@[^@]*)/\2\1/' } function fediusernametolink { grep -oE '(@[^@ ]+){2}' |sed -E 's|(@[^@ ]+)@([^@ ]+)|https://\2/\1|' }rld@Intrepid:~$ clipo https://polymaths.social/@rl_dane/statuses/01KVJCAG6Y4C1KTGBDBECH2778 rld@Intrepid:~$ clipo |fedilinktousername @[email protected] rld@Intrepid:~$ clipo |fedilinktousername |fediusernametolink https://polymaths.social/@rl_dane rld@Intrepid:~$ -
In the #shell #functions I should have written years ago category...
function fedilinktousername { grep -oE 'https?://[^/]+/@[^/ ]+' |sed -E 's|https?://|@|; s|/@|@|; s/(@[^@]*)(@[^@]*)/\2\1/' } function fediusernametolink { grep -oE '(@[^@ ]+){2}' |sed -E 's|(@[^@ ]+)@([^@ ]+)|https://\2/\1|' }rld@Intrepid:~$ clipo https://polymaths.social/@rl_dane/statuses/01KVJCAG6Y4C1KTGBDBECH2778 rld@Intrepid:~$ clipo |fedilinktousername @[email protected] rld@Intrepid:~$ clipo |fedilinktousername |fediusernametolink https://polymaths.social/@rl_dane rld@Intrepid:~$ -
In the #shell #functions I should have written years ago category...
function fedilinktousername { grep -oE 'https?://[^/]+/@[^/ ]+' |sed -E 's|https?://|@|; s|/@|@|; s/(@[^@]*)(@[^@]*)/\2\1/' } function fediusernametolink { grep -oE '(@[^@ ]+){2}' |sed -E 's|(@[^@ ]+)@([^@ ]+)|https://\2/\1|' }rld@Intrepid:~$ clipo https://polymaths.social/@rl_dane/statuses/01KVJCAG6Y4C1KTGBDBECH2778 rld@Intrepid:~$ clipo |fedilinktousername @[email protected] rld@Intrepid:~$ clipo |fedilinktousername |fediusernametolink https://polymaths.social/@rl_dane rld@Intrepid:~$ -
In the #shell #functions I should have written years ago category...
function fedilinktousername { grep -oE 'https?://[^/]+/@[^/ ]+' |sed -E 's|https?://|@|; s|/@|@|; s/(@[^@]*)(@[^@]*)/\2\1/' } function fediusernametolink { grep -oE '(@[^@ ]+){2}' |sed -E 's|(@[^@ ]+)@([^@ ]+)|https://\2/\1|' }rld@Intrepid:~$ clipo https://polymaths.social/@rl_dane/statuses/01KVJCAG6Y4C1KTGBDBECH2778 rld@Intrepid:~$ clipo |fedilinktousername @[email protected] rld@Intrepid:~$ clipo |fedilinktousername |fediusernametolink https://polymaths.social/@rl_dane rld@Intrepid:~$ -
Seriously, why didn't I put this in my
~/.bashrclike... YEARS ago? 😆year=$( date +%Y) month=$(date +%m) day=$( date +%d) -
Seriously, why didn't I put this in my
~/.bashrclike... YEARS ago? 😆year=$( date +%Y) month=$(date +%m) day=$( date +%d) -
Seriously, why didn't I put this in my
~/.bashrclike... YEARS ago? 😆year=$( date +%Y) month=$(date +%m) day=$( date +%d) -
Seriously, why didn't I put this in my
~/.bashrclike... YEARS ago? 😆year=$( date +%Y) month=$(date +%m) day=$( date +%d) -
Seriously, why didn't I put this in my
~/.bashrclike... YEARS ago? 😆year=$( date +%Y) month=$(date +%m) day=$( date +%d) -
Some POSIX #ShellScripting resources I've had bookmarked since before the question #WhyTheFuckDoesAIHaveToRuinEverything needed to be asked:
Rich’s sh (POSIX shell) tricks: https://www.etalabs.net/sh_tricks.html
GitHub - dylanaraps/pure-sh-bible: 📖 A collection of pure POSIX sh alternatives to external processes. · GitHub: https://github.com/dylanaraps/pure-sh-bible
POSIX Shell Tutorial: https://www.grymoire.com/Unix/Sh.html
-
Some POSIX #ShellScripting resources I've had bookmarked since before the question #WhyTheFuckDoesAIHaveToRuinEverything needed to be asked:
Rich’s sh (POSIX shell) tricks: https://www.etalabs.net/sh_tricks.html
GitHub - dylanaraps/pure-sh-bible: 📖 A collection of pure POSIX sh alternatives to external processes. · GitHub: https://github.com/dylanaraps/pure-sh-bible
POSIX Shell Tutorial: https://www.grymoire.com/Unix/Sh.html
-
Some POSIX #ShellScripting resources I've had bookmarked since before the question #WhyTheFuckDoesAIHaveToRuinEverything needed to be asked:
Rich’s sh (POSIX shell) tricks: https://www.etalabs.net/sh_tricks.html
GitHub - dylanaraps/pure-sh-bible: 📖 A collection of pure POSIX sh alternatives to external processes. · GitHub: https://github.com/dylanaraps/pure-sh-bible
POSIX Shell Tutorial: https://www.grymoire.com/Unix/Sh.html
-
Some POSIX #ShellScripting resources I've had bookmarked since before the question #WhyTheFuckDoesAIHaveToRuinEverything needed to be asked:
Rich’s sh (POSIX shell) tricks: https://www.etalabs.net/sh_tricks.html
GitHub - dylanaraps/pure-sh-bible: 📖 A collection of pure POSIX sh alternatives to external processes. · GitHub: https://github.com/dylanaraps/pure-sh-bible
POSIX Shell Tutorial: https://www.grymoire.com/Unix/Sh.html
-
Day 2/60 #BashSecurity -- Variables and types
Bash's "type system" is: everything is a string. This causes real security issues.
```bash
# This is an injection vulnerability:
user_in="file.txt; cat /etc/shadow"
grep $user_in /var/log/auth.log# This is safe:
grep "$user_in" /var/log/auth.log
```Other gotchas:
- `declare -i num=5; num="abc"` silently sets num to 0
- `export SECRET` makes it readable via /proc/self/environ
- `readonly CFG=/etc/app` prevents runtime tampering
- `x = 5` (with spaces) runs x as a command, not assignmentQuote every expansion. Validate every input. Trust nothing.
-
Test TCP Connectivity With Bash
#shellscripting #bash #network
https://sketchesfromahomelab.com/articles/2026/03/01/Test_TCP_Connectivity_With_Bash/ -
Test TCP Connectivity With Bash
#shellscripting #bash #network
https://sketchesfromahomelab.com/articles/2026/03/01/Test_TCP_Connectivity_With_Bash/ -
Wrote a #shell function without using
lsinside of$( ), so my inner @mirabilos won't harass me. XD#slightly easier wireguard command function wg { local dir file profile profiledir= parm=${1:-} statustext #Find profile dir for dir in {,/usr/local}/etc/wireguard; do if [[ -d $dir ]]; then profiledir=$dir break fi done #Find config file if [[ -n $profiledir ]]; then for file in $profiledir/*.conf; do if [[ -e $file ]]; then profile=${file//*\/} profile=${profile/.conf} break fi done fi [[ -n $profile ]] || profile=proton statustext="wireguard profile $profile" case ${parm,,} in up|on) doas wg-quick up $profile;; down|off) doas wg-quick down $profile;; status) echo -en "$statustext _______\r" echo -en "$statustext " ifconfig |grep -q "^$profile:" && echo enabled || echo disabled;; *) warn "wg usage: wg up|down|status";; esac }Hmm, seems
${foo,,}for lower case conversion is #bash-only. I wonder if I should usetrinstead. -
Wrote a #shell function without using
lsinside of$( ), so my inner @mirabilos won't harass me. XD#slightly easier wireguard command function wg { local dir file profile profiledir= parm=${1:-} statustext #Find profile dir for dir in {,/usr/local}/etc/wireguard; do if [[ -d $dir ]]; then profiledir=$dir break fi done #Find config file if [[ -n $profiledir ]]; then for file in $profiledir/*.conf; do if [[ -e $file ]]; then profile=${file//*\/} profile=${profile/.conf} break fi done fi [[ -n $profile ]] || profile=proton statustext="wireguard profile $profile" case ${parm,,} in up|on) doas wg-quick up $profile;; down|off) doas wg-quick down $profile;; status) echo -en "$statustext _______\r" echo -en "$statustext " ifconfig |grep -q "^$profile:" && echo enabled || echo disabled;; *) warn "wg usage: wg up|down|status";; esac }Hmm, seems
${foo,,}for lower case conversion is #bash-only. I wonder if I should usetrinstead. -
Wrote a #shell function without using
lsinside of$( ), so my inner @mirabilos won't harass me. XD#slightly easier wireguard command function wg { local dir file profile profiledir= parm=${1:-} statustext #Find profile dir for dir in {,/usr/local}/etc/wireguard; do if [[ -d $dir ]]; then profiledir=$dir break fi done #Find config file if [[ -n $profiledir ]]; then for file in $profiledir/*.conf; do if [[ -e $file ]]; then profile=${file//*\/} profile=${profile/.conf} break fi done fi [[ -n $profile ]] || profile=proton statustext="wireguard profile $profile" case ${parm,,} in up|on) doas wg-quick up $profile;; down|off) doas wg-quick down $profile;; status) echo -en "$statustext _______\r" echo -en "$statustext " ifconfig |grep -q "^$profile:" && echo enabled || echo disabled;; *) warn "wg usage: wg up|down|status";; esac }Hmm, seems
${foo,,}for lower case conversion is #bash-only. I wonder if I should usetrinstead. -
Zsh: select generated files with (om[1]) glob qualifiers - Adam Johnson
https://adamj.eu/tech/2026/01/27/zsh-om1-glob-qualifiers/ -
@heinelo das kann ich gut nachvollziehen, allerdings würde ich auch ins Feld führen, daß #macos im Kern auch ein linuixes System ist und von daher so genutzt werden kann.
In der graphischen Industrie sind #adobe Produkte einfach nicht weg zu denken. Deswegen verwende ich meine #mac Rechner eher wie #opensource Plattformen. Installationen werden mit #shellscripting erledigt und Programme mit #homebrew installiert.
Ich verwende keine AppleIDs, eigene Clouds, Aressbücher, Kalender und einen eigenen Mailserver bei Kunden und bei mir selbst.
So finde ich ist ein #macos ein unabhängiges System, welches auch keinem #killswitch ausgesetzt sein wird, denn sollte sich Apple dazu entscheiden keine Updates mehr zu liefern – was ich nicht glaube – dann installiere ich mir auf den Geräten #Linux, was ich eh schon mit meinen alten #apple Rechnern gemacht habe. -
@heinelo das kann ich gut nachvollziehen, allerdings würde ich auch ins Feld führen, daß #macos im Kern auch ein linuixes System ist und von daher so genutzt werden kann.
In der graphischen Industrie sind #adobe Produkte einfach nicht weg zu denken. Deswegen verwende ich meine #mac Rechner eher wie #opensource Plattformen. Installationen werden mit #shellscripting erledigt und Programme mit #homebrew installiert.
Ich verwende keine AppleIDs, eigene Clouds, Aressbücher, Kalender und einen eigenen Mailserver bei Kunden und bei mir selbst.
So finde ich ist ein #macos ein unabhängiges System, welches auch keinem #killswitch ausgesetzt sein wird, denn sollte sich Apple dazu entscheiden keine Updates mehr zu liefern – was ich nicht glaube – dann installiere ich mir auf den Geräten #Linux, was ich eh schon mit meinen alten #apple Rechnern gemacht habe. -
@heinelo das kann ich gut nachvollziehen, allerdings würde ich auch ins Feld führen, daß #macos im Kern auch ein linuixes System ist und von daher so genutzt werden kann.
In der graphischen Industrie sind #adobe Produkte einfach nicht weg zu denken. Deswegen verwende ich meine #mac Rechner eher wie #opensource Plattformen. Installationen werden mit #shellscripting erledigt und Programme mit #homebrew installiert.
Ich verwende keine AppleIDs, eigene Clouds, Aressbücher, Kalender und einen eigenen Mailserver bei Kunden und bei mir selbst.
So finde ich ist ein #macos ein unabhängiges System, welches auch keinem #killswitch ausgesetzt sein wird, denn sollte sich Apple dazu entscheiden keine Updates mehr zu liefern – was ich nicht glaube – dann installiere ich mir auf den Geräten #Linux, was ich eh schon mit meinen alten #apple Rechnern gemacht habe. -
Recursion usually scares me a bit, but it worked out nicely here:
#convert "cx"-style Esperanto notation to native accents (ĉ) function eaccent { if [[ ${1:-} ]]; then echo "$*" |eaccent else sed 's/cx/ĉ/g; s/gx/ĝ/g; s/hx/ĥ/g; s/jx/ĵ/g; s/sx/ŝ/g; s/ux/ŭ/g; s/C[xX]/Ĉ/g; s/G[xX]/Ĝ/g; s/H[xX]/Ĥ/g; s/J[xX]/Ĵ/g; s/S[xX]/Ŝ/g; s/U[xX]/Ŭ/g' fi }#bash #unix #shell #scripts #scripting #UnixShell #ShellScripting #Esperanto