To ignore commands that start with a space character, use the
HIST_IGNORE_SPACE option in bash or zsh.
setopt HIST_IGNORE_SPACE
Posts tagged: bash
All posts with the tag "bash"
32 posts
latest post 2026-05-24
Publishing rhythm
Vaulted Secrets Without Git Churn
Ansible Vault keeps secrets out of sight, but the ciphertext changes on every
encrypt. That turns Git [1] diffs into noise and makes it hard to tell if anything
actually changed. Decrypting, editing, and re-encrypting often leaves
uncertainty about whether any plaintext changed. This is amplified when secret
repos are tightly coupled to dependent repositories. A typical cycle includes
decrypting, adding a key, updating a value, applying changes, and returning
later with little clarity about what changed while secrets were in plaintext.
Today a new workflow was created with @gpt-5.2-codex to keep diffs clean and
avoid re-encrypting when the plaintext is identical.
[2]Waylon Walker
This repo has ansible vaulted secrets and an encrypt/decrypt process, but no
way to compare. Please research compare options. The goal is to avoid
changing files on encrypt/decrypt when plaintext is unchanged, ideally by
comparing decrypted content and reusing the remote encrypted file.
@gpt-5.2-codex
...
setting COLUMNS env var to a number greater than 0 will make the terminal resize to that number of columns.
COLUMNS=80 uvx --from rich-cli rich myscript.py
Note
Not all programs respct the COLUMNS env var, but rich does, and a lot of
stuff I’m building uses rich.
I discovered this when I was trying to make a low effort readme generated from
the code, but did not depend on the size of terminal it was ran on.
# justfile
readme:
echo "# Workspaces" > README.md
echo "" >> README.md
echo '``` bash' >> README.md
COLUMNS=80 ./workspaces.py --help >> README.md
echo '```' >> README.md
Today I learned how to use tar over ssh to save hours in file transfers. I
keep all of my projects in ~/git [1] (very creative I know, I’ve done it for years
and haven’t changed). I just swapped out my main desktop from bazzite to
hyprland, and wanted to get all of my projects back. Before killing my
bazzite install I moved everything over (16GB of many small files), it took
over 14 hours, maybe longer. I had started in the morning and just let it
churn.
This was not going to happen for re-seeding all of my projects on my new
system, I knew there had to be a better way, I looked at rsync, but for seeding
I ran into this tar over ssh technique and it only took me 6m51s to pull all of
my projects off of my remote server.
ssh [email protected] 'tar -C /tank/git -cpf - .' \
| tar -C "$HOME/git" -xpf -
References:
[1]: /glossary/git/
[1]2025-07-09 Notes [1] from yesterday I have temporal stuff kind of going with postiz in a windsurf session working on [[thoughts-to-nostr]] Been cleaning up my z" loading="lazy">
2025-07-10 Notes | Nic Payne
2025-07-09 Notes [2] from yesterday I have temporal stuff kind of going with postiz in a windsurf session working on [[thoughts-to-nostr]] Been cleaning up my z
pype.dev
big fan of eza and dust, I like these aliases to have some common commands at my fingertips. I often use the tree command and yes it sometimes goes too deep to actually be useful.
alias lt='eza -T --level=2' # Tree view, 2 levels deep
alias ltt='eza -T --level=3' # Tree view, 3 levels deep
alias du1='dust -d 1' # Show only 1 level deep
alias du2='dust -d 2' # Show 2 levels deep
Note
This post is a thought [3]. It’s a short note that I make
about someone else’s content online #thoughts
References:
[1]: https://pype.dev/2025-07-10-notes/
[2]: /2025-07-09-notes/
[3]: /thoughts/
I am a linux user through and through. Desktop, server, vms, containers,
everything except my phone is linux. With this I spend a lot of time in the
terminal, and have been a long time user of !! to rerun the last command, but
with the ability to tack something on at the beginning or end.
TIL about fc, which opens the last command in your shell history in your
$EDITOR or pass in your editor -e nvim.
man fc [1]
Rcap of how !! works # [2]
!! pronounces bang bang and will run the last command in your history.
ls -l
!! | wc -l
# ls -l | wc -l
sudo !!
# sudo ls -l | wc -l
!!:s/-l/-l \/tmp
# sudo ls -l /tmp | wc -l
fc enters the chat # [3]
Now making complex edits in your shell can be a bit of a chore, so fc moves
this work to your $EDITOR.
fc
This pops open your $EDITOR with the last command in your history.
sudo ls -l | wc -l
[4]
Shell History # [5]
fc shows up in shell history, but !! does not, !! gets replaced by the
command that it becomes.
Up Arrow # [6]
yaya yaya, I know you can also up-arrow c-e, but what fun is that, it’s barely a
flex. fc just looks big brained and like you really know what you are doing.
References:
[1]: https://manned.org/fc
[2]: #rcap-of...
You can unset multiple environment variables at once. I did not know this was a
thing, its something that ended up happening organically on a call and asking
someone to run unset. They had never done it before and did not know how it
works, but did exactly as I said instead of what I meant. I like this handy
shortcut doing it in one line rather than each one individually, I will be
using this in the future. You might need this for something like
running aws cli commands with localstack [1].
unset AWS_ACCESS_KEY_ID AWS_SECRET_ACCESS_KEY AWS_DEFAULT_REGION
References:
[1]: /running-aws-cli-commands-with-localstack/
bic
Static blog generator, in bash
bic · bic.sh [1]
Intereresting someone built a blog generator in bash. it comes with normal markdown to html [2], static content, robots.txt, sitemap, rss, and tags. It uses pandoc to take markdown to html and mustache for page templates.
Note
This post is a thought [3]. It’s a short note that I make
about someone else’s content online #thoughts
References:
[1]: https://bic.sh/
[2]: /html/
[3]: /thoughts/
GitHub - casey/just: 🤖 Just a command runner
🤖 Just a command runner. Contribute to casey/just development by creating an account on GitHub.
GitHub · github.com [1]
new versions of just now come with color variables already set.
[group('manage')]
version:
#!/usr/bin/env bash
version=$(cat version)
echo current version {{BOLD}}{{GREEN}}$version{{NORMAL}}
Note
This post is a thought [2]. It’s a short note that I make
about someone else’s content online #thoughts
References:
[1]: https://github.com/casey/just?tab=readme-ov-file#constants
[2]: /thoughts/
pipely/justfile at main · thechangelog/pipely
I like the idea of having like this 20-line Varnish config that we deploy around the world, and it’s like: Look at our CDN! - thechangelog/pipely
GitHub · github.com [1]
I found this nugget in thechangelogs justfile, it lets you add color to your justfile with variables quite easily.
# https://linux.101hacks.com/ps1-examples/prompt-color-using-tput/
_BOLD := "$(tput bold)"
_RESET := "$(tput sgr0)"
_BLACK := "$(tput bold)$(tput setaf 0)"
_RED := "$(tput bold)$(tput setaf 1)"
_GREEN := "$(tput bold)$(tput setaf 2)"
_YELLOW := "$(tput bold)$(tput setaf 3)"
_BLUE := "$(tput bold)$(tput setaf 4)"
_MAGENTA := "$(tput bold)$(tput setaf 5)"
_CYAN := "$(tput bold)$(tput setaf 6)"
_WHITE := "$(tput bold)$(tput setaf 7)"
_BLACKB := "$(tput bold)$(tput setab 0)"
_REDB := "$(tput setab 1)$(tput setaf 0)"
_GREENB := "$(tput setab 2)$(tput setaf 0)"
_YELLOWB := "$(tput setab 3)$(tput setaf 0)"
_BLUEB := "$(tput setab 4)$(tput setaf 0)"
_MAGENTAB := "$(tput setab 5)$(tput setaf 0)"
_CYANB := "$(tput setab 6)$(tput setaf 0)"
_WHITEB := "$(tput setab 7)$(tput setaf 0)"
Usage
echo:
echo {{_BOLD}}{{_GREEN}}hello there{{_RESET}}
Note
This post i...
Today I discovered the Urllink function in bash from the ujust tool from
ublue.it [1]. Seems like a cool trick, but might not work
everywhere.
########
### Special text formating
########
## Function to generate a clickable link, you can call this using
# url=$(Urllink "https://ublue.it" "Visit the ublue website")
# echo "${url}"
function Urllink (){
URL=$1
TEXT=$2
# Generate a clickable hyperlink
printf "\e]8;;%s\e\\%s\e]8;;\e\\" "$URL" "$TEXT${n}"
}
```j
References:
[1]: https://ublue.it
hostnamectl to easily change hostname | Nic Payne
hostnamectl is apparently a linux utility for easily changing your hostname in a variety of ways I learned there's transient and static hostnames, so that&
pype.dev [1]
For some reason the ublue ecosystem does not prompt you to set your hostname on install and you get a hostname like bazzite showing up. Looks like this is the fix.
hostnamectl –static hostname babyblue-aurora
Note
This post is a thought [2]. It’s a short note that I make
about someone else’s content online #thoughts
References:
[1]: https://pype.dev/hostnamectl-to-easily-change-hostname
[2]: /thoughts/
I’ve had a couple of uploads to twitter fail recently and has been a pain. I
tried some online converters for convenience, but none of them worked. I
reached out to chatgpt and found succeess with this ffmpeg command.
ffmpeg -i input.mp4 \
-vf "scale=trunc(oh*a/2)*2:min(720\,trunc(ih*a/2)*2)" \
-c:v libx264 -profile:v high -level:v 4.1 \
-b:v 3500k -maxrate 3500k -bufsize 7000k \
-pix_fmt yuv420p \
-c:a aac -b:a 128k -ar 44100 \
-movflags +faststart \
output.mp4
Authentication from cli tools can be a bit of a bear, and I have to look it up
every time. This is my reference guide for future me to remember how to easily
do it.
I set up a fastapi [1] server running on port 8000, it uses a basic auth with
waylonwalker as the username and asdf as the password. The server follows
along with what comes out of the docs. I have it setup to take basic auth,
form username and password, or a bearer token for authentication.
curl # [2]
The og [3] of command line url tools.
# basic auth
curl -u 'waylonwalker:asdf' -X POST localhost:8000/token
# basic auth with password prompt
curl -u 'waylonwalker' -X POST localhost:8000/token
# token
curl -H 'Authorization: bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiJ3YXlsb253YWxrZXIiLCJleHAiOjE3MDI5NTI2MDJ9.GeYNt7DNal6LTiPoavJnqypaMt4vYeriXdq5lqu1ILg' -X POST localhost:8000/token
wget # [4]
My go to if I want the result to go into a file.
# basic auth
wget -q -O - --auth-no-challenge --http-user=waylonwalker --http-password=asdf --post-data '' localhost:8000/token
# token
wget -q -O - --header="Authorization: bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiJ3YXlsb253YWxrZXIiLCJleHAiOjE3MDI5NT...
jpillora/installer is the install script generator I have been looking for. It
downloads binaries for your machine from GitHub releases and unzips them for
you. It grabs the latest release, so you can easily update them. I have
tried scripting these installs in the past and struggled to consistently get
the latest version for every package and unpack it correctly.
Also these pre-compiled binaries install rediculously fast compared to building
them from source.
Check out some example links.
opening in a browser will show metadata
https://i.jpillora.com/serve
If you pass in script=true it will instead return the install script as it
would by default through curl.
https://i.jpillora.com/serve?script=true
Use it to install neovim # [1]
All you need to do to generate an install script is to pass in the GitHub repo
slug with the org.
curl https://i.jpillora.com/neovim/neovim | bash
The shell script that it generates for neovim looks like this.
#!/bin/bash
if [ "$DEBUG" == "1" ]; then
set -x
fi
TMP_DIR=$(mktemp -d -t jpillora-installer-XXXXXXXXXX)
function cleanup {
rm -rf $TMP_DIR > /dev/null
}
function fail {
cleanup
msg=$1
echo "============"
echo "Error: $msg" 1>&2
...
Deleting Specific Lines in a File with sed or yq — Nick Janetakis
We
Nick Janetakis · nickjanetakis.com [1]
sed can be a tricky beast, I often stumble when trying to pipe into it. Next time I need to use sed, I should reference this article by Nick Janetakis. He makes it looks much easier than my experience has been, and it appears to behave like a vim :%s/ substitution does, or a g/ g command.
Note
This post is a thought [2]. It’s a short note that I make
about someone else’s content online #thoughts
References:
[1]: https://nickjanetakis.com/blog/deleting-specific-lines-in-a-file-with-sed-or-yq
[2]: /thoughts/
Give github actions the -e flag in the shebang #! so they fail on any one
command failure. Otherwise each line will set the exit status, but only the
last one will be passed to ci.
#!/bin/bash -e
What is -e # [1]
The -e flag to the bash command allows your script to exit immediately if any
command within the script returns a non-zero exit status. This can be useful
for ensuring that your script exits with an error if any of the commands it
runs fail, which can help you identify and debug issues in your script. For
example, if you have a script that runs several commands and one of those
commands fails, the script will continue running without the -e flag, but will
exit immediately if the -e flag is present. This can make it easier to
troubleshoot your script and ensure that it runs correctly.
Solution for Windows # [2]
In windows the solution is not quite as simple. You can define a function in a
Windows batch script that wraps an if statement to check the exit status of a
command and handle any errors that may have occurred. Here is an example of how
you might define a function called “check_error” that does this:
:check_error
if errorlevel 1 (
echo An error occurred!
ex...
I am often editing my own scripts as I develop them. I want to make a better
workflow for working with scripts like this.
Currently # [1]
Currently I am combining nvim with a which subshell to etit these files
like this.
for now lets use my todo command as an example
nvim `which todo`
First pass # [2]
On first pass I made a bash function to do exactly what I have been doing.
ewhich () {$EDITOR `which "$1"`}
The $1 will pass the first input to the which subshell. Now we can edit our todo script like this.
ewich todo
Note, I use bash functions instead of aliases for things that require input.
Final State # [3]
This works fine for commands that are files, but not aliases or shell
functions. Next I jumped to looking at the output of command -V $1.
- if the command is not found, search for a file
- if its a builtin, exit
- if its an alias, open my ~/.alias file to that line
- if its a function, open my ~/.alias file to that line
ewhich () {
case `command -V $1` in
"$1 not found")
FILE=`fzf --prompt "$1 not found searching ..." --query $1`
[ -z "$FILE" ] && echo "closing" || $EDITOR $FILE;;
*"is a shell builtin"*)
echo "$1 is a builtin";;
*"is an alias"*)
$EDITOR...
This morning I was trying to install a modpack on my minecraft server after
getting a zip file, and its quite painful when I unzip everything in the
current directory rather than the directory it belongs in.
I had the files on a Windows Machine # [1]
So I’ve been struggling to get mods installed on linux lately and the easiest
way to download the entire pack rather than each mod one by one seems to be to
use the overwolf application on windows. Once I have the modpack I can start
myself a small mod-server by zipping it, putting it in a mod-server directory
and running a python http.server
python -m http.server
Downoading on the server # [2]
Then I go back to my server and download the modpack with wget.
wget 10.0.0.171:8000/One%2BBlock%2BServer%2BPack-1.4.zip
Unzip to the minecraft-data directory # [3]
Now I can unzip my mods into the minecraft-data directory.
unzip One+Block+Server+Pack-1.4.zip -d minecraft-data
Running the server with docker # [4]
I run the minecraft server with docker, which is setup to mount the
minecraft-data directory.
Running a Minecraft Server in Docker [5]
A bit more on that in the other post, but when I download the whole modpack
like this I ...
There is GNU coreutils command called mktemp that is super handy in shell
scripts to make temporary landing spots for files so that they never clash with
another instance, and will automatically get cleaned up when you restart, or
whenever /tmp gets wiped. I’m not sure when that is, but I don’t expect it
to be long.
Making temp directories # [1]
Here are some examples of making temp directories in different places, my
favorite is mktemp -dt mytemp-XXXXXX.
# makes a temporary directory in /tmp/ with the defaul template tmp.XXXXXXXXXX
mktemp
# makes a temporary directory in your current directory
mktemp --directory mytemp-XXXXXX
# shorter version
mktemp -d mytemp-XXXXXX
# same thing, but makes a file
mktemp mytemp-XXXXXX
# makes a temporary directory in your /tmp/ directory (or what ever you have configured as your TMPDIR)
mktemp --directory --tmpdir mytemp-XXXXXX
# shorter version
mktemp -dt mytemp-XXXXXX
# same thing, but makes a file
mktemp --tmpdir mytemp-XXXXXX
# shorter version
mktemp -t mytemp-XXXXXX
Use Case # [2]
Here is a sample script that shows how to capture the tempdir as a variable and
reuse it. Here is an example of curling my bootstrap file into a temp
dir...