8 Commits

13 changed files with 445 additions and 23 deletions

View File

@@ -1,8 +1,11 @@
### Some GNU/Linux tools, for fun...
### Some personal GNU/Linux tools.
#### bash
- **trans.sh**: a [linguee.com](https://linguee.com) based command-line translator.
- **sync.sh**: a rsync/ssh backup tool.
- **sync-view.sh**: view ~sync.sh~ file backups versions.
- **sync-conf-example.sh**: configuration example.
- **dup-live-disk.sh**: duplicate (possibly live) disk partitions.
- **dup-live-disk.sh**: duplicate (**possibly live**) disk partitions.
- **gen-password.sh**: a password generator.
- **base.sh**: bases 2/8/10/16 conversions.

View File

@@ -1,11 +1,10 @@
### Some GNU/Linux tools, for fun...
#### bash
### Some bash scripts, that I needed at some time...
- [**trans.sh**](trans.sh): a [linguee.com](https://linguee.com) based command-line translator.
- [**sync.sh**](sync.sh): a rsync/ssh backup tool.
- [**sync-conf-example.sh**](share/sync/sync-conf-example.sh): configuration example.
- [**sync-view.sh**](sync-view.sh): view `sync.sh` file backups versions.
- [**dup-live-disk.sh**](dup-live-disk.sh): duplicate (possibly live) disk partitions.
- [**gen-password.sh**](gen-password.sh): a password generator
- [**share/gen-password**](share/gen-password): [diceware](https://en.wikipedia.org/wiki/Diceware)-like word lists.
- [**base**](base.sh): bases 2/8/10/16 conversions.

283
bash/base.sh Executable file
View File

@@ -0,0 +1,283 @@
#!/usr/bin/env bash
#
# base.sh - convert decimal numbers from/to base 2, 8, 10 and 16.
#
# (C) Bruno Raoult ("br"), 2024
# Licensed under the GNU General Public License v3.0 or later.
# Some rights reserved. See COPYING.
#
# You should have received a copy of the GNU General Public License along with this
# program. If not, see <https://www.gnu.org/licenses/gpl-3.0-standalone.html>.
#
# SPDX-License-Identifier: GPL-3.0-or-later <https://spdx.org/licenses/GPL-3.0-or-later.html>
#
CMDNAME=${0##*/} # script name
usage() {
printf "usage: %s [OPTIONS] [NUMBER]...\n" "$CMDNAME"
printf "Use '%s -h' for more help\n" "$CMDNAME"
}
help() {
cat << _EOF
usage: $CMDNAME [OPTIONS] [NUMBER]...
-f, --from=BASE input base. Default is "g"
-t, --to=BASE output base. Default is "a"
-2, -8, -d, -x equivalent to -t2, -t8, -t10, -t16"
-g, --group=[SEP] group output (see OUTPUT below)
-0, --padding Not implemented. 0-pad output on block boundary (implies -g)
-n, --noprefix Remove base prefixes in output
-h, --help this help
$CMDNAME output the NUMBERS arguments in different bases. If no NUMBER is
given, standard input will be used.
BASE
2, b, B binary
8, o, O, 0 octal
10, d, D decimal
16, h, H, 0x hexadecimal
a, g all/any: Default, guess format for '-f', output all
bases for '-t'
INPUT NUMBER
If input base is not specified, some prefixes are supported.
'b' or '2/' for binary, '0', 'o' or '8/' for octal, '0x', 'x' or
'16/' for hexadecimal, and 'd' or '10/' for decimal.
If no prefix, decimal is assumed.
OUTPUT
By default, output is the input number converted in the 4 supported
bases (16, 10, 8, 2, in this order, separated by one tab character.
Without '-n' option, all output numbers but decimal will be prefixed:
'2#' for binary, '0' for octal, '0x' for hexadecimal, making them
usable for input in some otilities such as bash(1).]
With '-g' option, number digits will be grouped by 3 (octal,
decimal), or 4 (binary, hexadecimal)\n. If no SEP character is given,
the separator will be ',' (comma) for decimal, space otherwise.
This option may be useless if default output, with multiple numbers
on one line.
The '-0' option will left pad with '0' (zeros) to a group boundary.
EXAMPLES
$ $CMDNAME 123456
2#11110001001000000 0361100 123456 0x1e240
$ $CMDNAME -n 123456
11110001001000000 361100 123456 1e240
$ $CMDNAME -ng2 012345
1 0100 1110 0101
$ $CMDNAME -n2 012345
1 0100 1110 0101
_EOF
}
# some default values (blocks separator padchar)
declare -i ibase=0 obase=0 padding=0 noprefix=0 ogroup=0
declare -rA _bases=(
[2]=2 [b]=2 [B]=2
[8]=8 [o]=8 [O]=8 [0]=8
[10]=10 [d]=10 [D]=10
[16]=16 [h]=16 [H]=16 [0x]=16
[a]=-1 [g]=-1
)
declare -A _pad=(
[2]=" " [8]=" " [10]="," [16]=" "
)
declare -rA _ogroup=(
[2]=4 [8]=3 [10]=3 [16]=4
)
declare -rA _oprefix=(
[2]="2#" [8]="0" [10]="" [16]="0x"
)
zero_pad() {
local base="$1" str="$2"
local str="$1"
local -i n=${_ogroup[$base]}
#printf "str=$str #=${#str}" >&2
while (( ${#str} < $2 )); do
str="0$str"
done
printf "%s" "$str"
}
split() {
local base="$1" str="$2"
local res="$str" sep=${_pad[$base]}
local -i n=${_ogroup[$base]}
if (( ogroup )); then
res=""
while (( ${#str} )); do
if (( ${#str} < n )); then
str=$(zero_pad "$str" $n)
fi
res="${str: -$n}${res:+$sep$res}"
str="${str:0:-$n}"
done
fi
printf "%s" "$res"
}
bin() {
local n bits=""
for (( n = $1 ; n > 0 ; n >>= 1 )); do
bits=$((n&1))$bits
done
printf "%s\n" "${bits-0}"
}
hex() {
printf "%lx" "$1"
}
dec() {
printf "%lu" "$1"
}
oct() {
printf "%lo" "$1"
}
declare -a args=()
parse_opts() {
# short and long options
local sopts="f:t:28dxg::pnh"
local lopts="from:,to:,group::,padding,noprefix,help"
# set by options
local tmp=""
if ! tmp=$(getopt -o "$sopts" -l "$lopts" -n "$CMDNAME" -- "$@"); then
usage
exit 1
fi
eval set -- "$tmp"
while true; do
case "$1" in
"-f"|"--from")
ibase=${_bases[$2]}
if (( ! ibase )); then
usage
exit 1
fi
shift
;;
"-t"|"--to")
obase=${_bases[$2]}
if (( ! obase )); then
usage
exit 1
fi
shift
;;
"-2") obase=2 ;;
"-8") obase=8 ;;
"-d") obase=10 ;;
"-x") obase=16 ;;
"-g"|"--group")
ogroup=1
if [[ -n "$2" ]]; then
for i in 2 8 10 16; do _pad["$i"]="$2"; done
fi
shift
;;
"-p"|"--padding") padding=1 ;;
"-n"|"--noprefix") noprefix=1 ;;
"-h"|"--help") help ; exit 0 ;;
"--") shift; break ;;
*) usage; echo "Internal error [$1]!" >&2; exit 1 ;;
esac
shift
done
# parse remaining arguments
if (($# > 0)); then # type
args=("$@")
fi
}
# shellcheck disable=SC2317
addprefix() {
local base="$1" number="$2"
local prefix=""
(( noprefix )) || prefix="${_oprefix[$base]}"
printf "%s%s" "$prefix" "$number"
}
stripprefix() {
local number="$1"
number=${number#0x}
number=${number#[bodx0]}
number=${number#0}
number=${number#*/}
printf "%s" "$number"
}
guessbase() {
local input="$1"
local -i base=0
if [[ $input =~ ^b || $input =~ ^2/ ]]; then
base=2
elif [[ $input =~ ^0x || $input =~ ^x || $input =~ ^16/ ]]; then
base=16
elif [[ $input =~ ^0 || $input =~ ^o || $input =~ ^8/ ]]; then
base=8
elif [[ $input =~ ^d || $input =~ ^10/ ]]; then
base=10
fi
return $(( base ? base : 10 ))
}
doit() {
local number="$2" multi="" val inum
local -i base=$1 decval _obase=$obase
if (( base <= 0 )); then
guessbase "$number"
base=$?
fi
inum=$(stripprefix "$number")
(( decval = "$base#$inum" )) # input value in decimal
# mask for desired output: 1=decimal, others are same as base
if (( ! _obase )); then
(( _obase = 1|2|8|16 ))
multi=$'\t'
fi
if (( _obase & 16 )); then
val=$(addprefix 16 "$(split 16 "$(hex $decval)")")
printf "%s%s" "$val" "$multi"
fi
if (( _obase & 1 )); then
val=$(addprefix 10 "$(split 10 "$(dec $decval)")")
printf "%s%s" "$val" "$multi"
fi
if (( _obase & 8 )); then
val=$(addprefix 8 "$(split 8 "$(oct $decval)")")
printf "%s%s" "$val" "$multi"
fi
if (( _obase & 2 )); then
val=$(addprefix 2 "$(split 2 "$(bin $decval)")")
printf "%s%s" "$val" "$multi"
fi
printf "\n"
}
parse_opts "$@"
if ! (( ${#args[@]} )); then
while read -ra line; do
for input in "${line[@]}"; do
doit "ibase" "$input"
done
done
else
for input in "${args[@]}"; do
doit "$ibase" "$input"
done
fi
exit 0

View File

@@ -565,8 +565,8 @@ parse_opts() {
local c2="" c3=""
local -i i
if ! tmp=$(getopt -o "$sopts" -l "$lopts" -n "$CMD" -- "$@"); then
log "Use '$CMD --help' or '$CMD --man' for help."
if ! tmp=$(getopt -o "$sopts" -l "$lopts" -n "$CMDNAME" -- "$@"); then
log "Use '$CMD --help' or 'zob $CMDNAME --man' for help."
exit 1
fi

18
config/home/bash_profile Normal file
View File

@@ -0,0 +1,18 @@
#!/usr/bin/env bash
#
# ~/.bash_profile - bash login script.
#
# (C) Bruno Raoult ("br"), 2024
# Licensed under the GNU General Public License v3.0 or later.
# Some rights reserved. See COPYING.
#
# You should have received a copy of the GNU General Public License along with this
# program. If not, see <https://www.gnu.org/licenses/gpl-3.0-standalone.html>.
#
# For login shells, ~/.profile is executed. Debian default one does:
# 1) source .bashrc if it exists
# 2) add "$HOME"/bin in PATH
# This imply a duplicate "$HOME/bin" in PATH, as we do everything in .bashrc.$user.
# Having this ~/.bash_profile will avoid the execution of ~/.profile
[ -f "$HOME/.bashrc" ] && . "$HOME/.bashrc"

View File

@@ -2,7 +2,7 @@
#
# ~/.bashrc.br - user specific initialization
#
# (C) Bruno Raoult ("br"), 2001-2023
# (C) Bruno Raoult ("br"), 2001-2024
# Licensed under the GNU General Public License v3.0 or later.
# Some rights reserved. See COPYING.
#
@@ -14,6 +14,12 @@
# Usage: to be invoked from .bashrc.
# i.e., add at the end of .bashrc:
# [ -f "$HOME/.bashrc.$USER" ] && . "$HOME/.bashrc.$USER"
#
# Debian default ~/.profile does:
# 1) source .bashrc if it exists
# 2) add "$HOME"/bin in PATH
# This imply a duplicate "$HOME/bin" in PATH, as we do everything here.
# Better to have a ~/.bash_profile with the lines above.
# _var_del() - remove an element from a colon-separated list.
# $1: name (reference) of a colon separated list
@@ -150,6 +156,16 @@ else
fi
export EDITOR=$VISUAL
# look for a pdf viewer
for _pdfviewer in qpdfview atril; do
if hash "$_pdfviewer" 2>/dev/null; then
# shellcheck disable=SC2139
alias acroread="$_pdfviewer"
break
fi
done
unset _pdfviewer
# append to the history file, don't overwrite it
shopt -s histappend
# write history after each command
@@ -173,7 +189,7 @@ export QUOTING_STYLE=literal
# avoid these stupid systemd defaults (horizontal scroll and pager)
alias systemctl="systemctl --no-pager --full"
# aliases for ls and history
# useful aliases/functions
alias l='ls -F'
alias ls='ls -F'
alias l1='ls -1F'
@@ -207,6 +223,10 @@ alias hl="history 25" # long
alias hll="history 100" # very long
alias hlll="history" # all history
alias grep='grep --color=auto' # add colors to grep
alias fgrep='fgrep --color=auto'
alias egrep='egrep --color=auto'
# user temp directory
export USERTMP=~/tmp
@@ -245,6 +265,19 @@ rehash() {
alias trans="trans.sh"
alias rtrans="trans.sh -fen -tfr"
# easy directory sync (remove source trailing slash)
syncdir() {
local -a opts=(--archive --hard-links --one-file-system --itemize-changes --delete)
local src="$1" dst="$2"
case "$src" in
*[!/]*/)
src=${src%"${src##*[!/]}"};;
*[/])
src="/";;
esac
rsync "${opts[@]}" "$src" "$dst"
}
# host specific initialization
# shellcheck disable=SC1090
[ -f "$HOME/.bashrc.$USER.$(hostname)" ] && . "$HOME/.bashrc.$USER.$(hostname)"

View File

@@ -0,0 +1,82 @@
#!/usr/bin/env bash
#
# ~/.bashrc.br.eowyn - host specific initialization
#
# (C) Bruno Raoult ("br"), 2001-2024
# Licensed under the GNU General Public License v3.0 or later.
# Some rights reserved. See COPYING.
#
# You should have received a copy of the GNU General Public License along with this
# program. If not, see <https://www.gnu.org/licenses/gpl-3.0-standalone.html>.
#
# SPDX-License-Identifier: GPL-3.0-or-later <https://spdx.org/licenses/GPL-3.0-or-later.html>
#
# Usage: to be invoked from .bashrc.$USER
# i.e., add at the end of .bashrc.$USER:
# [ -f "$HOME/.bashrc.$USER.$(hostname)" ] && . "$HOME/.bashrc.$USER.$(hostname)"
# mysql aliases. Will match any "[client-XXX]" lines in ~/.my.cnf
# and generate "myXXX" aliases.
if [[ -r ~/.my.cnf ]]; then
mapfile -t MYSQL_ARRAY < ~/.my.cnf
for line in "${MYSQL_ARRAY[@]}"; do
if [[ $line =~ ^\[client-(.+)\]$ ]]; then
SUFFIX="${BASH_REMATCH[1]}"
# shellcheck disable=SC2139,SC2140
alias my"$SUFFIX"="mysql --defaults-group-suffix=-$SUFFIX"
fi
done
fi
# shortcuts to commonly used directories/projects
# _vardir() - define common dirs vars & aliases
# $1: name variable to set
# $2: name of alias to define
# $3: script to source (relative to $2). '-': no script, '+': './script/env.sh'
# $4: project path
#
# _vardir() sets variable with $1 name to $4, and an alias with $2 name.
# The alias, when invoked, will:
# (1) change working directory to $1
# (2) source $3 when $3 is not '-'. $3 path can be relative (preferred), or
# absolute. If $3 is "+", it will default to "scripts/env.sh".
#
# Examples:
# _vardir MYDIR mydir - ~/foo/mydirprj
_vardir() {
local _v="$1" _a="$2" _s="$3" _p="$4"
if [[ ! -d $_p ]]; then
printf "ignored project: %s\n" "$_p"
return 0
fi
local _x="cd $_p"
export "$_v"="$_p"
case "$_s" in
-) ;;
+) _s="scripts/env.sh" ;&
*) if [[ -r "$_p/$_s" ]]; then
_x+="; . $_s"
else
printf "%s: ignored.\n" "$_p/$_s"
fi
esac
# shellcheck disable=SC2139
alias "$_a"="$_x"
}
#_vardir AOC aoc + ~/dev/advent-of-code # Advent of code
_vardir WCHESS wchess - ~/dev/www/crd/chess # raoult.com chess
_vardir CHESS chess + ~/dev/brchess # brchess
_vardir TOOLS tools - ~/dev/tools # tools
_vardir BRLIB brlib - ~/dev/brlib # brlib
#_vardir EUD eud + ~/dev/eudyptula # eudyptula
_vardir DEV dev - ~/dev # dev
# Indent style for emacs
# Local Variables:
# mode: shell-script
# sh-basic-offset: 4
# sh-indentation: 4
# indent-tabs-mode: nil
# End:

View File

@@ -2,7 +2,7 @@
#
# ~/.bashrc.br.lorien - host specific initialization
#
# (C) Bruno Raoult ("br"), 2001-2023
# (C) Bruno Raoult ("br"), 2001-2024
# Licensed under the GNU General Public License v3.0 or later.
# Some rights reserved. See COPYING.
#
@@ -15,9 +15,6 @@
# i.e., add at the end of .bashrc.$USER:
# [ -f "$HOME/.bashrc.$USER.$(hostname)" ] && . "$HOME/.bashrc.$USER.$(hostname)"
# look for a pdf viewer
hash atril 2> /dev/null && alias acroread=atril
# mysql aliases. Will match any "[client-XXX]" lines in ~/.my.cnf
# and generate "myXXX" aliases.
if [[ -r ~/.my.cnf ]]; then
@@ -44,17 +41,21 @@ fi
# The alias, when invoked, will:
# (1) change working directory to $1
# (2) source $3 when $3 is not '-'. $3 path can be relative (preferred), or
# absolute. If $3 is "+", it will default to "./scripts/env.sh".
# absolute. If $3 is "+", it will default to "scripts/env.sh".
#
# Examples:
# _vardir MYDIR mydir - ~/foo/mydirprj
_vardir() {
local _v="$1" _a="$2" _s="$3" _p="$4"
if [[ ! -d $_p ]]; then
printf "ignored project: %s\n" "$_p"
return 0
fi
local _x="cd $_p"
export "$_v"="$_p"
case "$_s" in
-) ;;
+) _s="./scripts/env.sh" ;&
+) _s="scripts/env.sh" ;&
*) if [[ -r "$_p/$_s" ]]; then
_x+="; . $_s"
else

View File

@@ -1,7 +1,7 @@
;;;; ~/.Emacs.d/init.el
;;;;
;;;; emacs configuration
;;;; br, 2010-2023
;;;; br, 2010-2024
;;;;
;;;; all personal variables/defun are prefixed with "my/".
;;
@@ -34,8 +34,7 @@
"Directory where to store all temp and backup files.")
(setq backup-directory (concat my/emacs-tmpdir "/backups/")
save-directory (concat my/emacs-tmpdir "/autosave/")
auto-save-list-file-prefix (concat my/emacs-tmpdir "/autosave-list/")
)
auto-save-list-file-prefix (concat my/emacs-tmpdir "/autosave-list/"))
;; create dirs if necessary
(dolist (dir (list backup-directory save-directory auto-save-list-file-prefix))
@@ -340,6 +339,9 @@ Return new LIST-VAR value."
tramp-verbose 1)
;; (customize-set-variable 'tramp-syntax 'simplified)
;; Emacs 29.1 ?
;;(autoload #'tramp-register-crypt-file-name-handler "tramp-crypt")
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; conf mode
;; strangely ".cnf" is not here...
(use-package conf-mode
@@ -460,7 +462,7 @@ Return new LIST-VAR value."
tab-width 2 ; default tab width
)
(setq-default indent-tabs-mode nil)
(setq-default indent-tabs-mode nil) ; no tabs
(icomplete-mode 0) ; minibuffer completion
; soooo sloooow
@@ -758,7 +760,7 @@ in whole buffer. With neither, delete comments on current line."
;; https://emacs.stackexchange.com/questions/10955
(advice-add #'vc-git-mode-line-string :filter-return #'my/replace-git-status)
(defun my/replace-git-status (tstr)
"Replace git `variable:vc-mode' string with a modified followed by TSTR."
"Replace git `variable:vc-mode' string with a UTF8 symbol followed by TSTR."
(let* ((tstr (replace-regexp-in-string "Git" "" tstr))
(first-char (substring tstr 0 1))
(rest-chars (substring tstr 1)))
@@ -891,10 +893,11 @@ in whole buffer. With neither, delete comments on current line."
:diminish helm-mode
:init
;;(progn
;;(require 'helm-config)
;;(require 'helm-autoloads)
;; (require 'helm-config)
;; (require 'helm-autoloads)
(require 'pcomplete)
(require 'helm-projectile)
;; (require 'tramp)
(setq
helm-candidate-number-limit 100
;; From https://gist.github.com/antifuchs/9238468