1
2
 
 

I've seen : "${DB_HOST:=localhost}" because it assigns the variable if not set (: $… is just to run assignments standalone).

But that has the same effect like DB_HOST="${DB_HOST:-localhost} (use the string if not set), which is more readable.

While something like echo "${DB_HOST:=localhost}" smells from a mile, because it has output with side-effects.

3
4
 
 

cross-posted from: https://lemmy.ml/post/35169329

Using a shell script, can I watch a folder and block program execution until a file in a certain folder changes?

5
 
 

This is a little tutorial that I found in my search to learn how to use getopt (mind: not getopts, which is a completely different thing). I want to share it here because I find it refreshingly to the point. Just the main code block already tells almost the whole story:

#!/bin/bash
# Set some default values:
ALPHA=unset
BETA=unset
CHARLIE=unset
DELTA=unset

usage()
{
  echo "Usage: alphabet [ -a | --alpha ] [ -b | --beta ]
                        [ -c | --charlie CHARLIE ] 
                        [ -d | --delta   DELTA   ] filename(s)"
  exit 2
}

PARSED_ARGUMENTS=$(getopt -a -n alphabet -o abc:d: --long alpha,bravo,charlie:,delta: -- "$@")
VALID_ARGUMENTS=$?
if [ "$VALID_ARGUMENTS" != "0" ]; then
  usage
fi

echo "PARSED_ARGUMENTS is $PARSED_ARGUMENTS"
eval set -- "$PARSED_ARGUMENTS"
while :
do
  case "$1" in
    -a | --alpha)   ALPHA=1      ; shift   ;;
    -b | --beta)    BETA=1       ; shift   ;;
    -c | --charlie) CHARLIE="$2" ; shift 2 ;;
    -d | --delta)   DELTA="$2"   ; shift 2 ;;
    # -- means the end of the arguments; drop this, and break out of the while loop
    --) shift; break ;;
    # If invalid options were passed, then getopt should have reported an error,
    # which we checked as VALID_ARGUMENTS when getopt was called...
    *) echo "Unexpected option: $1 - this should not happen."
       usage ;;
  esac
done

echo "ALPHA   : $ALPHA"
echo "BETA    : $BETA "
echo "CHARLIE : $CHARLIE"
echo "DELTA   : $DELTA"
echo "Parameters remaining are: $@"

Just be sure to correct the inadvertent mixing of beta and bravo.

6
 
 

Edit: I figured it out: The solution is over a process substitution operator:

join <(echo "$var1") <(echo "$var2")

See also the comment by @notabot@piefed.social below, this StackOverflow comment, and the GNU documentation..


It's comparatively straightforward to use the content of one variable in join by using - to tell it to use standard input for that file:

echo $variable | join - anotherfile

However, is there a way to serve both input 'files' from variables, avoiding temporary files on the disk?

It seems like the easiest way would be via creating and mounting a temporary partition via tmpfs,

mount -t tmpfs -o size=50m tmpfs /mountpoint,

and just create temporary files in there. And afterwards clean things up.

So far I've also attempted here-documents, but apparently this too can only provide standard input, so that the other input still has to be served from a file.

Maybe one can also try doing it via named pipes (mkfifo), but I fear this could introduce lots of potentialities for errors.

7
 
 

Let me show you what I mean by giving an example:

# Assume we have this list of increasing numbers
140
141
145
180
190
...

# If we pick 150 as threshold, the output should consist of 145 and all larger values:
145
180
190
...

# In the edge case where 150 itself is in the list, the output should start with 150:
150
180
190
...

I guess one can always hack something together in awk with one or two track-keeper variables and a bit of control logic. However, is there a nicer way to do this, by using some nifty combination of simpler filters or awk functionalities?

One way would be to search for the line number n of the first entry larger than the threshold, and then print all lines starting with n-1. What command would be best suited for that?

Still, I'm also wondering: Can awk or any other standard tool do something like "for deciding whether to print this line, look at the next line"?

(In my use case, the list is short, so performance is not an issue, but maybe let's pretend that it were. Also, in my use case, all entries are unique, but feel free to work without this assumption.)

8
 
 

Ever since I started down the self-hosting rabbit hole one issue I've been constantly annoyed with is transferring files between machines. Especially files which I am currently working on and that I want to periodically transfer to a specific remote location.

Rsync has been my go to tool for file transfers and backups but I absolutely hate making commands for it. I was getting lost in a wall of text with all my rsync aliases.

The script I created helps me organize those commands by placing all the information for an rsync command into an easier to read dot-file. The script will read the dot-file, update the rsync command and run it. It's also set up to preview file transfers with rsync's dry run option. I've also added a few other features to make the script more flexible including being able to quickly backup a directory that I'm currently working in.

For self-hosting, I find working with files a bit easier to organize than a text full of aliases although I can see it easy to get overwhelmed with dot-files if some people aren't organized.

I've also made it as POSIX shell friendly as possible. I know a couple things I did aren't fully POSIX compliant currently but I that's something to work towards. This is also the first programming thing I ever completed so I'm quite happy with how it turned out.

If at least one other person finds this script useful, that would be pretty neat :)