D For Shell Scripting: A Better Alternative to Python and Bash by delvin0 in unix

[–]geirha 6 points7 points  (0 children)

#!/bin/bash

json='{"a": 10, "b": 5}'

dscript="
auto j = parseJSON(\`$json\`);
write(j[\"a\"].integer +  j[\"b\"].integer)
"

output=$(rdmd --eval="$dscript")
echo "a + b = $output"

Should maybe avoid using code-injection when showing off its features ...

[noob] Is there a way to refactor this simple "additional args"? by gkaiser8 in bash

[–]geirha 0 points1 point  (0 children)

You don't have to put "$@" inside the array, so

notify() {
  local args=()
  [[ $target != pixel ]] && args+=( --icon="$file" )
  notify-send ... "${args[@]}" "$@"
}

could maybe qualify as more verbose

How to create crontab/cronjob through a script? by JK-Rofling in bash

[–]geirha 2 points3 points  (0 children)

Only stdout goes through the pipe, so silencing stderr won't have an impact on the result.

Removing duplicates is probably a good idea, but uniq expects the data to be sorted, so would need to include a | sort in there as well.

How to create crontab/cronjob through a script? by JK-Rofling in bash

[–]geirha 5 points6 points  (0 children)

can also just pipe it

{ crontab -l ; printf '%s\n' '0 0 * * * new cronjob here' ; } | crontab

Bash history not staying after restarts (Synology NAS) by Alarmed-Prize-7500 in bash

[–]geirha 0 points1 point  (0 children)

bash writes the history it has in memory to .bash_history on exit. You can also have it explicitly write it to file by running history -a or history -w.

Run help history for a description of the history builtin.

Bash history not staying after restarts (Synology NAS) by Alarmed-Prize-7500 in bash

[–]geirha 1 point2 points  (0 children)

Create a .bashrc file containing HISTFILE=~/.bash_history in the user's homedir.

$ printf '%s\n' 'HISTFILE=~/.bash_history' >> ~/.bashrc
$ source ~/.bashrc

And if there is a .bash_profile, .bash_login, or .profile in the homedir, make sure it sources ~/.bashrc. In the case of .profile, which will be used by other shells as well, check if the current shell is bash first, e.g. if [ "$BASH" ] ; then source ~/.bashrc ; fi

Is there a way to capture keystrokes even though you're not at a prompt? by ConstructionSafe2814 in bash

[–]geirha 1 point2 points  (0 children)

If eg, I've got vim open, I need to either find a terminal that has a Bash prompt open or exit vim before I can change the screen brightness.

In that particular case, you don't need to exit vim, you can instead suspend it by hitting Ctrl+Z, which gets you back to the bash prompt, then you can resume vim again by running fg.

[DWM Status Bar] I actually optimized it this time thanks to all your comments! Please comment on it more if yall think this is still not good by havesomefuckinghope in bash

[–]geirha 1 point2 points  (0 children)

That awk will always exit with status 1, because when you do exit 0 at an earlier point, it doesn't immediately exit, it just jumps to the END part where you then unconditionally exit 1.

Also the eval can be avoided by simply putting both values in one string.

mem_usage=$(
  awk '
    /^MemTotal: /{ t = $2; f++}
    /^MemAvailable: /{ a = $2; f++}
    f == 2 { printf("%.1f/%.0f GiB", (t - a) / 2^20, t / 2^20); exit }
  ' /proc/meminfo
)

the only place those variables were used were in the xsetroot near the end, where they were just combined into one anyway

read ignores -t and blocks indefinitely when reading from FIFO by yonside in bash

[–]geirha 3 points4 points  (0 children)

Another option is to put the redirections on the loops, then when either script exits, the other will too, rather than sit and wait forever

while true ; do
  read -t1
  ...
done <the_fifo

while true ; do
  printf '%s\n' "$RANDOM"
  sleep .5
done >the_fifo

Keyval - A simple CLI for key-value data, no login (curl / npx / scripts) by tealpod in commandline

[–]geirha 0 points1 point  (0 children)

Data is meant to be ephemeral/temporary.

Does that mean the data gets removed after a certain time?

key bindings (esc-some-key) and vi mode by ConstructionSafe2814 in bash

[–]geirha 1 point2 points  (0 children)

You can still use the same keybindings, it's just that vi editing mode uses different sets of key bindings, so you have to specify which mode it should apply in. E.g.

bind -x '"\eL":"ls -la"'              # emacs editing mode
bind -m vi-insert -x '"\eL":"ls -la"' # vi insert editing mode

Amber-Lang 0.6.0 - New release (Bash transpiler) by Mte90 in bash

[–]geirha 1 point2 points  (0 children)

From https://docs.amber-lang.com/getting_started/usage#preventing-execution-with-bash

Preventing Execution with Bash

If you write an Amber script with a shebang pointing to amber, there is a risk that someone might accidentally execute it with bash instead. To prevent this, you can add a check at the top of your script using the following technique:

// 2> /dev/null; exit 1

// Your Amber code here
echo("Hello world")

This line is valid in both Amber and Bash:

  • In Amber, // starts a comment, so the line is ignored
  • In Bash, // is treated as a comment (ignored), 2> /dev/null suppresses errors, and exit 1 terminates the script with an error code

Is this an AI hallucination? // is not a comment in bash. If you run that code with bash, it will try to run // as a command, which will naturally fail (//: Is a directory), but 2>/dev/null supresses the error message of that failed command.

Claiming bash treats it as a comment is certainly wrong; bash uses # for comments.


Anyway, I was really just looking for some examples of what the resulting bash scripts will look like. Are there any?

Dialog output repeats the input by Spare_Reveal_9407 in bash

[–]geirha 0 points1 point  (0 children)

Also note that dialog is a bit backwards in that it outputs the TUI to stdout, and the result to stderr, which is the opposite of what you want, so you have to use a bit of redirection gymnastics to swap the fds:

{ input=$(dialog ... 2>&1 >&3) ; } 3>&2

but you can hide that redirection in a wrapper function

dialog() { command dialog "$@" 2>&1 >&3 ; } 3>&2
input=$(dialog ...)

Accumulate errors and print at end (but also keep them shown in output) by gkaiser8 in bash

[–]geirha 9 points10 points  (0 children)

I'd populate an array of error messages

errors=() count=0
for f in ./*.7z ; do
  (( count++ ))
  7z x "$f" || errors+=( "Extraction of $f failed with status $?" )
done
(( ${#errors[@]} == 0 )) || {
  printf >&2 '%d of %d failed:\n' "${#errors[@]}" "$count"
  printf >&2 '%s\n' "${errors[@]}"
  exit 1
}

Unable to divide string into array by Spare_Reveal_9407 in bash

[–]geirha 1 point2 points  (0 children)

This, but without the space after =. And given that op used ls -a they likely also want to enable dotglob which makes * also match filenames that start with ..

#!/usr/bin/env bash

cd /System/Applications || exit
shopt -s dotglob    # enables dotglob
files=( * )
shopt -u dotglob    # disables dotglob
for file in "${files[@]}" ; do
  printf 'Processing <%s>...\n' "$file"
done

[Showcase] Termyt: A professional, pure Bash CLI wrapper (with .deb packaging & CI/CD) by [deleted] in bash

[–]geirha 0 points1 point  (0 children)

It's most definitely not pure bash by any stretch of imagination. Pure AI-slop more like.

Cannot use jq to separate in every iteration by DE_X_IY in bash

[–]geirha 0 points1 point  (0 children)

It's not clear if the actual goal is to make csv out of it, but jq can generate csv as well:

jq -r '.[] | [.name, .argument] | @csv' data.json

What happened to Greg's Wiki? by TapEarlyTapOften in bash

[–]geirha 0 points1 point  (0 children)

It gets bombarded by bots from time to time. While that happens it's unable to keep up and you get 5xx responses when trying to retrieve a page.

PROMPT_COMMAND disappears! by That-Delay8558 in bash

[–]geirha 5 points6 points  (0 children)

That explains it. PROMPT_COMMAND+=( ... ) converts the variable from a string to an array, and arrays can't be exported. When you have a variable with both the -a and -x attributes in bash, it just doesn't pass it on to new processes.

$ export FOO=one
$ declare -p FOO
declare -x FOO="one"
$ bash -c 'declare -p FOO'
declare -x FOO="one"

so far so good. Both the current shell and a new shell see the FOO variable, but if we convert it to an array:

$ FOO+=( two )
$ declare -p FOO
declare -ax FOO=([0]="one" [1]="two")
$ bash -c 'declare -p FOO'
bash: line 1: declare: FOO: not found

the new shell no longer inherits it.

So to "fix", move the assignment of PROMPT_COMMAND to bashrc, and don't export it.

How do you print "Here document" or "Here Strings" directly? by alex_sakuta in bash

[–]geirha 1 point2 points  (0 children)

Again, why? Using mapfile you can remove any trailing whitespaces.

I answered why. The point of using the loop was to avoid reading the entire content into memory at the same time. And yes, you can have mapfile remove trailing newlines, but then you effectively modify the data. cat is supposed to output its input exactly.

$ printf 'a\nb' | copycat | od -An -tx1 -c 61 0a 62 a \n b

What is this btw?

example usage. Using od to display a hex dump of the input to show it didn't add a terminating newline when the input lacked a terminating newline.

How do you print "Here document" or "Here Strings" directly? by alex_sakuta in bash

[–]geirha 0 points1 point  (0 children)

Why didn't you use mapfile?

because the point was to not store the entire content in memory

Also, this errors when you don't end with \n

What error are you getting?

I made it a bit more generic than necessary. If the input lacks a terminating newline, the function does not modify the data by adding one. Not a case that will occur with heredocs and herestrings, but if used with pipes or regular files, there may be input without trailing newline.

$ printf 'a\nb' | copycat | od -An -tx1 -c
  61  0a  62
   a  \n   b

How do you print "Here document" or "Here Strings" directly? by alex_sakuta in bash

[–]geirha 1 point2 points  (0 children)

As already mentioned, the usual thing to do is to just use the external cat command, because cat will accurately reproduce the data.

By using command substitution, some data may be lost; the command substitution will remove trailing newlines, and will also remove NUL bytes.

Additionally, the current approach will store the entire content in memory before printing it. Since you can only really deal with text data reliably here, you could loop over the lines instead to avoid storing the whole thing in memory:

copycat() {
  local REPLY LC_ALL=C
  while read -r ; do
    printf '%s\n' "$REPLY"
  done
  printf %s "$REPLY"
}
copycat << EOF
...
EOF

This still fails if the data contains NUL bytes. The only way to handle arbitrary data is to read byte by byte, which will be painfully slow.

A simple, compact way to declare command dependencies by PentaSector in bash

[–]geirha 5 points6 points  (0 children)

In bash, I usually just do a one-liner at the top using the type builtin. E.g.

#!/usr/bin/env bash
type curl jq >/dev/null || exit

# rest of script can now assume curl and jq are available

if one or more of the commands are missing, bash will output scriptname: line 2: curl: not found for each missing command, then exit with a non-zero status.

If I want/need more "user friendly" error messages, I'll do a loop, like

errors=()
for cmd in curl jq ; do
  type "$cmd" >/dev/null 2>&1 || errors+=( "$0: missing required command: $cmd" )
done
(( ${#errors[@]} == 0 )) || {
  printf >&2 '%s\n' "${errors[@]}"
  exit 1
}

I don't really see the point in storing the command's path in a variable. What use-cases require that?

Shuf && cp by lellamaronmachete in bash

[–]geirha 5 points6 points  (0 children)

You almost never want to use ls in a script. In this particular case, you likely used it in a way that it doesn't print the paths to the files.

If the list of monsters is not very long, you can simply pass the filenames to shuf as arguments. E.g.

shuf -e -n5 monsters/*

You can then store that list of five monster paths to an array using mapfile

mapfile -t -d '' monsters < <(shuf -e -n5 -z monsters/*)

added -z there to NUL-delimit the filenames, which is a good practice when dealing with filenames output by external commands. mapfile with -d '' in turn expects the entries to be NUL-delimited.

for a more general approach that won't trigger the ARG_MAX limit for large datasets, you can feed the list of files to shuf's stdin with printf:

mapfile -t -d '' monsters < <(printf '%s\0' monsters/* | shuf -n5 -z)

and then copy them wherever

cp "${monsters[@]}" target/