56 Commits

Author SHA1 Message Date
fatalerrors
e41c1a4c51 harden rmspc, better median calculation in file_stats 2026-03-25 16:10:41 +01:00
fatalerrors
60dfe19049 message type case unsensitive 2026-03-25 15:39:05 +01:00
fatalerrors
c32771a4ff default configuration updated 2026-03-25 15:28:08 +01:00
fatalerrors
080511d0bd add NO_COLOR support 2026-03-25 15:27:23 +01:00
fatalerrors
d8bdfefdf1 typo 2026-03-25 15:26:39 +01:00
fatalerrors
5f5f9c0e71 add trap protection, and option to force remplacement 2026-03-25 15:14:10 +01:00
fatalerrors
30387a4f08 update copyright info, uniformize sheebang 2026-03-25 14:39:58 +01:00
fatalerrors
0c51363d86 revert factorisation attempt 2026-03-25 14:37:20 +01:00
fatalerrors
043fbaef0b protect against code injection, interpret vars 2026-03-25 14:35:53 +01:00
fatalerrors
ed5587712e support for spaced filename 2026-03-25 14:19:08 +01:00
fatalerrors
58cc76c317 pre generate sections of the configuration file 2026-03-11 17:20:50 +01:00
fatalerrors
e82ee06e1d secured some implementation, check bash version 2026-03-11 11:41:56 +01:00
fatalerrors
bc8cb4a237 updated readme and final fixes for net.sh 2026-03-10 18:06:30 +01:00
fatalerrors
ae90a9f4c4 fix conf file comments, version bump 2026-03-10 17:46:30 +01:00
fatalerrors
7e661ca2de add dwl (downloader wrapper) and make use of it, fixed myextip 2026-03-10 17:45:26 +01:00
fatalerrors
9f22ed4304 fix show_as initialization 2026-03-10 15:23:52 +01:00
fatalerrors
1484b004be implemented showextip 2026-03-10 12:01:45 +01:00
fatalerrors
0a4206b890 fix getopt behavior 2026-03-10 11:40:37 +01:00
fatalerrors
02a1e25df2 fix profile.conf line endind 2026-03-10 11:02:31 +01:00
fatalerrors
7ca0a6fb88 fixed README, version bump 2026-03-10 10:55:02 +01:00
fatalerrors
25df408e37 implemented ini style parsed configuration file 2026-03-10 10:53:31 +01:00
fatalerrors
3eab1f98d5 fix parameter detection 2026-03-10 10:52:45 +01:00
fatalerrors
6c895b509a pursue --help implementation 2026-03-10 10:52:17 +01:00
fatalerrors
2ece711e1a huge longrun improvements 2026-03-06 17:46:26 +01:00
fatalerrors
39a7e7b40f version bump 2026-03-05 11:56:15 +01:00
fatalerrors
6d5d872b71 add a missing fi 2026-03-05 11:49:10 +01:00
fatalerrors
128cfe8c87 improved upgrade system, version bump 2026-03-05 11:25:05 +01:00
fatalerrors
e1c2705fdd added ppu and ppn 2026-03-05 11:20:23 +01:00
fatalerrors
368bc11acf add many compression format to utaz 2026-03-05 10:55:17 +01:00
fatalerrors
a068d57ba5 utaz finally work with many formats, with optimizations 2026-03-05 10:24:25 +01:00
fatalerrors
ffee8c2e47 added help to rain, fixed french comments 2026-03-04 16:17:36 +01:00
geoffray.levasseur
9ff5792790 configurable rain 2026-03-04 15:55:11 +01:00
root
6a2d9b0fee adaptation to trixie and excalibur 2025-11-19 14:35:40 +01:00
Geoffray Levasseur-Brandin
9b2c764181 typos 2025-06-19 14:50:46 +02:00
Geoffray Levasseur-Brandin
3d5a5e7718 typos 2025-06-19 14:50:21 +02:00
Geoffray Levasseur-Brandin
47e89b3b09 compress.sh: multiple correction and securisation 2025-06-19 14:49:49 +02:00
Geoffray Levasseur-Brandin
f0f80e2924 better display implementation 2025-06-19 14:47:14 +02:00
Geoffray Levasseur-Brandin
b08e457146 version bump 2025-06-19 14:42:14 +02:00
Geoffray Levasseur-Brandin
56e34bc346 few varaible securisation, new alias hdu 2025-06-19 14:41:31 +02:00
Geoffray Levasseur-Brandin
e9e9993dfc finished profile_uprade implementation 2025-06-19 14:40:02 +02:00
Geoffray Levasseur-Brandin
ff4c6702b7 secured rmhost 2025-06-19 14:39:10 +02:00
Geoffray Levasseur-Brandin
87dea45295 fixed some variable declarations 2025-06-19 14:38:18 +02:00
Geoffray Levasseur-Brandin
0abf481cf6 various improvement and securisation 2025-06-19 14:37:32 +02:00
Geoffray Levasseur-Brandin
a75299f7b4 non gnu date compatible, use local vars where possible 2025-06-19 14:36:13 +02:00
Geoffray Levasseur-Brandin
eeb87c5bfc make delay parametrable 2025-06-19 14:34:22 +02:00
Geoffray Levasseur-Brandin
4879b418db factorized code / thiner implementation 2025-06-19 14:33:36 +02:00
Geoffray Levasseur-Brandin
f944271488 added file_stats function 2025-06-19 14:32:29 +02:00
Geoffray Levasseur-Brandin
4be2e5ea87 add url encode / secure isipv4 2025-06-19 14:31:19 +02:00
Geoffray Levasseur-Brandin
9d528a6491 fix kt function 2025-06-19 14:30:38 +02:00
Geoffray Levasseur-Brandin
bef205ae84 bugfix, esthetic cleanup, better comments, version bump 2024-06-21 16:19:44 +02:00
Geoffray Levasseur
9e49e3e4d7 fixed url and redirection 2023-10-06 12:52:15 +02:00
94e7e79c76 Merge branch 'master' of https://git.geoffray-levasseur.org/fatalerrors/profile 2023-10-06 11:36:14 +02:00
55e88bd018 partial commit for profile upgrade 2023-10-06 11:35:40 +02:00
Geoffray Levasseur
18f1bc1543 fix bash/zsh test, some cosmetics 2023-10-06 11:22:10 +02:00
fatalerrors
0d7c7e9ab7 minor correction 2023-09-08 20:25:04 +02:00
root
64fecf16fb make profile path configurable as autodetection is too unprecise so far 2023-04-19 21:15:33 +00:00
21 changed files with 2654 additions and 794 deletions

View File

@@ -20,7 +20,8 @@ prompt. Here is a non-exhaustive list of what we have:
- A bar style prompt with hour, execution time and exit code of the last
command;
- clean: erase after confirmation any backup file, possibly recursively;
- dpkgs: search for the given pattern in the installed packages name;
- dwl: a curl/wget/fetch download wrapper;
- pkgs: search for the given pattern in the installed packages name;
- expandlist: usefull in scripts, it expand any expression using wildcards into
the corresponding list of file and directories;
- genpwd: generate one or more random secure password;
@@ -31,6 +32,7 @@ the corresponding list of file and directories;
- ku: kill all the processes owned by the given user name or ID;
- mcd: create a directory and immediately move into it;
- meteo: display weather forecast information;
- myextip: get informations about your public IP;
- ppg: look for the given patern in the running processes;
- rain: console screensaver with rain effect;
- rmhost: remove the given host (name or IP) to the list of SSH known host;
@@ -51,8 +53,9 @@ directory only if needed;
## 3. Configuration
Some functions might have configurable default behaviour. You can create a
.profile.conf file to configure those default behaviour. You should have a look
at the doc/.profile.conf.example to see the list of available options.
profile.conf file to configure those default behaviour. You should have a look
at the doc/profile.conf.example to see the list of available options. The
configuration file is located in the same directory as profile.sh file.
## 4. Contact and more information
### 4.1. New users

View File

@@ -7,6 +7,17 @@ Current version from Geoffray Levasseur <fatalerrors@geoffray-levasseur.org>
------------------------------------------------------------------------------
Version history:
------------------------------------------------------------------------------
# 05/03/2026 v3.6.1
Fix a typo in compress.sh
# 05/03/2026 v3.6.0
Improved utaz to make it multiformat with lot of it
Introduced ppu and ppn
Improved update system
# 04/03/2026 v3.5.0
rain has now configurable speed and color
showinfo adapted to fastfetch, replacing neofetch
# 24/02/2022 v3.3.1
Fixed version detection

90
profile.conf Executable file
View File

@@ -0,0 +1,90 @@
[system]
# System section is used to set Bash behavior and other system related
# variables, such as the default pager, the terminal type, etc.
# Set bash history
HISTSIZE=50000
HISTIGNORE="&:[bf]g:exit"
# Set default pager
PAGER=less
# Set terminal colors behavior
TERM=xterm-256color
[compress]
# Section used by compress.sh
[debug]
# Section used by debug.sh
[disp]
# Section used by disp.sh
# NO_COLOR=1 # Set to any value to disable colors in disp output
[filefct]
# Section used by filefct.sh
[fun]
# Section used by fun.sh
[info]
# Section used by info.sh
DEFAULT_CITY="Toulouse" # Default city for weather forcast
[lang]
# Section used by lang.sh
[net]
# Section used by net.sh
[packages]
# Section used by packages.sh
[prompt]
# Section used by prompt.sh
[pwd]
# Section used by pwd.sh
[rain]
# Section used by rain.sh
[ssh]
# Section used by ssh.sh
[updates]
# Section used by updates.sh
[general]
# General section allow to set any variable that can be used by the user.
# It is also a good place to set freely global variables for personal use.
# Set some compiling values
CFLAGS="-O2 -pipe -march=native"
CXXFLAGS="$CFLAGS"
MAKEFLAGS='-j12'
PKGSOURCES='/share/src/archives'
[aliases]
ll='ls -laFh --color=auto'
la='ls -Ah --color=auto'
l='ls -CF --color=auto'
ls='ls --color=auto'
grep='grep --color=auto'
egrep='egrep --color=auto'
fgrep='fgrep --color=auto'
qfind="find . -name "
mkck='make check'
mkin='make install'
mkdin='make DESTDIR=$PWD/dest-install install'
ssh='ssh -Y'
wget='wget -c' # resume mode by default
myip='curl ip.appspot.com'
# Human readable by default
df='df -H'
du='du -ch'
sdu='du -sk ./* | sort -n'
hdu='du -hs ./* | sort -H'

View File

@@ -1,5 +1,6 @@
#!/usr/bin/env bash
# ------------------------------------------------------------------------------
# Copyright (c) 2013-2022 Geoffray Levasseur <fatalerrors@geoffray-levasseur.org>
# Copyright (c) 2013-2026 Geoffray Levasseur <fatalerrors@geoffray-levasseur.org>
# Protected by the BSD3 license. Please read bellow for details.
#
# * Redistribution and use in source and binary forms,
@@ -34,109 +35,351 @@
# ------------------------------------------------------------------------------
# ------------------------------------------------------------------------------
# Smartly uncompress archives (zip only)
# ------------------------------------------------------------------------------
# Smartly uncompress archives
# Usage: utaz [option] [directorie(s)|file(s)]
# Options:
# -h, --help Display that help screen
# -d, --delete If decompression succeeded, delete the source file
# -c, --create-dir Always create a host directory
# -n, --no-dir Never create a host directory
utaz()
{
for opt in $@ ; do
case $opt in
"-h"|"--help")
echo "utaz: uncompress all the given files and/or the ones found in the given"
echo " directories creating an host directory where needed."
echo
echo "Usage: utaz [option] [directorie(s)|file(s)]"
echo
echo "Options:"
echo " -h, --help Display that help screen"
echo " -d, --delete If decompression succeeded, delete the source file"
echo " -c, --create-dir Always create a host directory"
echo " -n, --no-dir Never create a host directory"
echo
return 0
;;
_ununzip()
{
unzip -o "$1" -d "$2" >/dev/null 2>&1
}
"-d"|"--delete")
local willrm=1
;;
_untar()
{
tar -xf "$1" -C "$2"
}
"-c"|"--create-dir")
local createdir=1
;;
_ungzip()
{
tar -xzf "$1" -C "$2"
}
"-n"|"--no-dir")
local nodir=1
;;
_unbzip2()
{
tar -xjf "$1" -C "$2"
}
"-"*)
disp E "Invalid option, use \"utaz --help\" to display options list"
echo
return 1
;;
_unxz()
{
tar -xJf "$1" -C "$2"
}
*)
# The ${opt%/} writing is to remove trailing / if any
local LIST="$LIST ${opt%/}"
;;
_unlzop()
{
lzop -d "$1" -o "$2/$(basename "${1%.*}")"
}
_unlzip()
{
if command -v plzip >/dev/null 2>&1; then
plzip -d -c "$1" > "$2/$(basename "${1%.*}")"
else
lzip -d -c "$1" > "$2/$(basename "${1%.*}")"
fi
}
_ununrar()
{
unrar x -o+ "$1" "$2/" >/dev/null 2>&1
}
_ununarj()
{
unarj e "$1" "$2/" >/dev/null 2>&1
}
_unlza()
{
# lha typically extracts into the current directory
# We ensure it hits the target directory
(cd "$2" && lha -x "../$1") >/dev/null 2>&1
}
_ununace()
{
unace x "$1" "$2/" >/dev/null 2>&1
}
_un7z()
{
7z x "$1" -o"$2/" >/dev/null 2>&1
}
_unzstd()
{
# Zstd decompresses files directly, often requiring tar for archives
tar --zstd -xf "$1" -C "$2"
}
_uncpio()
{
# CPIO requires careful directory handling
(cd "$2" && cpio -id < "../$1") >/dev/null 2>&1
}
_uncabextract()
{
# Requires 'cabextract' package
cabextract "$1" -d "$2/" >/dev/null 2>&1
}
_undeb()
{
# Extracts data content from a Debian package
dpkg-deb -x "$1" "$2/" >/dev/null 2>&1
}
_unrpm()
{
# Extracts CPIO-based payload from an RPM package
# Needs rpm2cpio and cpio
rpm2cpio "$1" | (cd "$2/" && cpio -idmv) >/dev/null 2>&1
}
local PARSED=$(getopt -o hdcn --long help,delete,create-dir,no-dir -n 'utaz' -- "$@")
if [ $? -ne 0 ]; then
disp E "Invalid options, use \"utaz --help\" to display usage."
return 1
fi
eval set -- "$PARSED"
while true; do
case "$1" in
-h|--help)
printf "utaz: uncompress all the given files and/or the ones found in the given\n"
printf " directories creating an host directory where needed.\n\n"
printf "Usage: utaz [option] [directorie(s)|file(s)]\n\n"
printf "Options:\n"
printf "\t-h, --help\t\tDisplay that help screen\n"
printf "\t-d, --delete\t\tIf decompression succeeded, delete the source file\n"
printf "\t-c, --create-dir\tAlways create a host directory\n"
printf "\t-n, --no-dir\t\tNever create a host directory\n\n"
printf "Supported archive format:\n"
printf "\t- zip\n"
printf "\t- tar.gz, .tgz\n"
printf "\t- tar.bz2, .tbz2\n"
printf "\t- tar.xz, .txz\n"
printf "\t- tar.lz, .tlz\n"
printf "\t- rar\n"
printf "\t- arj\n"
printf "\t- lha, lzh\n"
printf "\t- ace\n"
printf "\t- 7z, p7z\n"
printf "\t- zst\n"
printf "\t- cpio\n"
printf "\t- cab\n"
printf "\t- deb\n"
printf "\t- rpm\n"
return 0
;;
-d|--delete)
local willrm=1
shift
;;
-c|--create-dir)
local createdir=1
shift
;;
-n|--no-dir)
local nodir=1
shift
;;
--)
shift
break
;;
*)
disp E "Invalid option, use \"utaz --help\" to display options list"
return 1
;;
esac
done
# The remaining arguments after -- are the files/directories to process,
# "." is used if none is given
local FILES=("$@")
[[ ${#FILES[@]} -eq 0 ]] && FILES=(".")
[[ $createdir && $nodir ]] && disp E "The --create-dir and --no-dir options are mutually exclusive."
[[ -n ${createdir} && -n ${nodir} ]] && \
disp E "The --create-dir and --no-dir options are mutually exclusive."
[[ ! $LIST ]] && local LIST="."
for zitem in $LIST; do
[[ $(ls $zitem/*.zip 2> /dev/null | wc -l) -eq 0 ]] &&
disp W "$zitem contains no supported archive file, skipping." &&
for zitem in "${FILES[@]}"; do
# Build list of input files to process, with whitespace-safe handling.
local targets=()
if [[ -f "$zitem" ]]; then
targets=("$zitem")
elif [[ -d "$zitem" ]]; then
mapfile -d '' -t targets < <(find "$zitem" -mindepth 1 -maxdepth 1 -print0 2>/dev/null)
if [[ ${#targets[@]} -eq 0 ]]; then
disp I "Directory ${zitem} is empty, skipping."
continue
fi
else
disp W "Path ${zitem} is not a file or directory, skipping."
continue
fi
for f in $zitem/*.zip; do
disp I "Processing archive $zitem/$f... "
local dir=${f::-4}
for f in "${targets[@]}"; do
local dir="${f%.*}"
local extractor=""
case "$f" in
*.zip)
extractor="_ununzip"
;;
*.tar.gz|*.tgz)
extractor="_ungzip"
;;
*.tar.bz2|*.tbz2)
extractor="_unbzip2"
;;
*.tar.xz|*.txz)
extractor="_unxz"
;;
*.tar.lz|*.tlz)
extractor="_unlzop"
;;
*.tar)
extractor="_untar"
;;
*.rar)
extractor="_ununrar"
;;
*.arj)
extractor="_ununarj"
;;
*.lzh|*.lha)
extractor="_unlha"
;;
*.ace)
extractor="_ununace"
;;
*.7z|*.p7z)
extractor="_un7z"
;;
*.zst)
extractor="_unzstd"
;;
*.cpio)
extractor="_uncpio"
;;
*.cab)
extractor="_uncabextract"
;;
*.deb)
extractor="_undeb"
;;
*.rpm)
extractor="_unrpm"
;;
*)
disp I "File ${f} is not a supported archive, skipping."
continue
;; # Skip non-archive files
esac
mkdir -p $dir
# Verify binary existence
local cmd=${extractor//_un/}
if [[ $cmd == "deb" ]]; then
command -v -- dpkg-deb >/dev/null 2>&1 || {
disp E "The program 'dpkg-deb' is not installed, aborting."
continue
}
elif [[ $cmd == "rpm" ]]; then
command -v -- rpm2cpio >/dev/null 2>&1 || {
disp E "The program 'rpm2cpio' is not installed, aborting."
continue
}
command -v -- cpio >/dev/null 2>&1 || {
disp E "The program 'cpio' is not installed, aborting."
continue
}
else
command -v -- "${cmd}" >/dev/null 2>&1 || {
disp E "Binary ${cmd} necessary to extract ${f} is missing."
continue
}
fi
disp I "Processing archive ${f} with ${extractor}..."
mkdir -p "${dir}"
[[ $? -gt 0 ]] &&
disp E "The filesystem can't create directories, exit!" &&
return 1
unzip -o $f -d $dir > /dev/null 2>&1
${extractor} "${f}" "${dir}"
case $? in
0)
[[ $willrm ]] && rm -f $f && disp I "File $zitem/$f deleted."
;;
1)
0)
[[ -n ${willrm} ]] &&
rm -f "${f}" && disp I "File ${zitem}/${f} deleted."
;;
1)
if [[ -n ${willrm} ]]; then
disp W "Compression program returned a warning: deletion canceled."
;;
*)
disp E "The zip file seems corrupted, failed."
rm -rf $dir > /dev/null 2>&1
continue
;;
else
disp W "Compression program returned a warning."
fi
;;
*)
disp E "The compressed file ${f} seems corrupted, failed."
rm -rf "${dir}" >/dev/null 2>&1
continue
;;
esac
if [[ $createdir ]]; then
if [[ -n ${createdir} ]]; then
disp I "Archive extracted successfully in subdirectory."
elif [[ $nodir ]]; then
mv ./$dir/* ./ && rmdir $dir
elif [[ -n ${nodir} ]]; then
shopt -s nullglob
for child in "${dir}"/*; do
mv -- "$child" .
done
shopt -u nullglob
rmdir -- "${dir}"
disp I "Archive extracted successfully, no subdirectory needed."
else
subdirs=$(find $dir -maxdepth 1 | wc -l)
if [[ $subdirs -eq 2 ]]; then
mv ./$dir/* ./ && rmdir $dir
# Set nullglob to ensure the array is empty if no files match
shopt -s nullglob
local contents=( "${dir}"/* )
# Check if exactly one item exists and if that item is a directory
if [[ ${#contents[@]} -eq 1 ]] && [[ -d "${contents[0]}" ]]; then
# Single directory detected
shopt -s nullglob
for child in "${contents[0]}"/*; do
mv -- "$child" .
done
shopt -u nullglob
rmdir -- "${dir}"
disp I "Archive extracted successfully, no subdirectory needed."
else
disp I "Archive extracted successfully in subdirectory."
fi
shopt -u nullglob
fi
done
done
}
export -f utaz
# ------------------------------------------------------------------------------
# ------------------------------------------------------------------------------
# Compress directories or files into one or more archive
# ------------------------------------------------------------------------------
taz ()
# Usage: taz [option] [--parallel=<n>] [--format=<format>] [directory1 ... directoryN]
# Options:
# -h, --help Display that help screen
# -d, --delete Delete source file or directory after success
# -f, --format Chose archive format in the given list. If several format are
# given, the smalest is kept
# -p, --parallel Number of threads to use (if allowed by underlying utility)
# -v, --verbose Display progress where possible
# -q, --quiet Display less messages (only errors and warnings)
# -1, .., -9 Compression level to use [1=fast/biggest, 9=slow/smallest]
taz()
{
_doxz()
{
@@ -166,11 +409,11 @@ taz ()
disp E "Program 'plzip' or 'lzip' are not installed, aborting."
return 127
}
local command=lzip
command=lzip
local procopt=""
[[ $2 -gt 1 ]] &&
disp W "lzip doesn't support multithreading, falling back to 1 thread." &&
disp W "Consitder installing plzip to obtain multithreading abilities."
disp W "Consider installing plzip to obtain multithreading abilities."
}
[[ $4 ]] && local verb="-vv"
@@ -194,7 +437,7 @@ taz ()
local procopt=""
[[ $2 -gt 1 ]] &&
disp W "gzip doesn't support multithreading, falling back to 1 thread." &&
disp W "Consitder installing pigz to obtain multithreading abilities."
disp W "Consider installing pigz to obtain multithreading abilities."
}
[[ $4 ]] && local verb="--verbose"
@@ -218,7 +461,7 @@ taz ()
local procopt=""
[[ $2 -gt 1 ]] &&
disp W "bzip2 doesn't support multithreading, falling back to 1 thread." &&
disp W "Consitder installing pbzip2 to obtain multithreading abilities."
disp W "Consider installing pbzip2 to obtain multithreading abilities."
}
[[ $4 ]] && local verb="-v"
@@ -243,85 +486,99 @@ taz ()
return $?
}
for opt in $@ ; do
case $opt in
"-h"|"--help")
echo "taz: archive all files of a directory."
echo
echo "Usage: taz [option] [--parallel=<n>] [--format=<format>] [directory1 ... directoryN]"
echo
echo "Options:"
echo " -h, --help Display that help screen"
echo " -d, --delete Delete source file or directory after success"
echo " -f, --format Chose archive format in the given list. If several format are"
echo " given, the smalest is kept"
echo " -p, --parallel Number of threads to use (if allowed by underlying utility)"
echo " -v, --verbose Display progress where possible"
echo " -q, --quiet Display less messages (only errors and warnings)"
echo " -1, .., -9 Compression level to use [1=fast/biggest, 9=slow/smallest]"
echo
echo "Supported archive format:"
echo " Param.| programs | Algo. | Description"
echo " ------+---------------+-------+----------------------------------------"
echo " lz | plzip, lzip | lzma | Safe efficient default format"
echo " xz | xz | lzma2 | Unsafe, not for long term"
echo " bz2 | pbzip2, bzip2 | bzip2 | Historical but less efficient than lz"
echo " gz | pigz, gzip | lz77 | Historical, safe, fast"
echo " lzo | lzop | lzo | Very fast but no multithread"
echo " tar | tar | tar | No compression"
echo
return 0
;;
local PARSED
PARSED=$(getopt -o hdf:p:vq123456789 --long help,delete,format:,parallel:,verbose,quiet --name "taz" -- "$@")
if [ $? -ne 0 ]; then
disp E "Invalid options, use \"taz --help\" to display usage."
return 1
fi
eval set -- "$PARSED"
while true; do
case "$1" in
-h|--help)
printf "taz: archive all files of a directory.\n\n"
printf "Usage: taz [option] [--parallel=<n>] [--format=<format>] [directory1 ... directoryN]\n\n"
printf "Options:\n"
printf "\t-h, --help\tDisplay that help screen\n"
printf "\t-d, --delete\tDelete source file or directory after success\n"
printf "\t-f, --format\tChose archive format in the given list. If several format are"
printf "\t\t\tgiven, the smalest is kept\n"
printf "\t-p, --parallel\tNumber of threads to use (if allowed by underlying utility)\n"
printf "\t-v, --verbose\tDisplay progress where possible\n"
printf "\t-q, --quiet\tDisplay less messages (only errors and warnings)\n"
printf "\t-1, .., -9\tCompression level to use [1=fast/biggest, 9=slow/smallest]\n\n"
printf "Supported archive format:\n"
printf "\tParam.| programs | Algo. | Description\n"
printf "\t------+---------------+-------+----------------------------------------\n"
printf "\t lz | plzip, lzip | lzma | Safe efficient default format\n"
printf "\t xz | xz | lzma2 | Unsafe, not for long term\n"
printf "\t bz2 | pbzip2, bzip2 | bzip2 | Historical but less efficient than lz\n"
printf "\t gz | pigz, gzip | lz77 | Historical, safe, fast\n"
printf "\t lzo | lzop | lzo | Very fast but no multithread\n"
printf "\t tar | tar | tar | No compression\n"
printf "\n"
return 0
;;
"-d"|"--delete")
local willrm=1
;;
-d|--delete)
local willrm=1
shift
;;
"-f"?*|"--format"?*)
local compform=$(echo "$opt" | cut -f 2- -d '=')
;;
-f|--format)
local compform=$2
shift 2
;;
"-p"?*|"--parallel"?*)
local nproc=$(echo "$opt" | cut -f 2- -d '=')
;;
-p|--parallel)
local nproc=$2
shift 2
;;
"-v"|"--verbose")
local verbose=1
;;
-v|--verbose)
local verbose=1
shift
;;
"-q"|"--quiet")
QUIET=1
;;
-q|--quiet)
local quiet=1
shift
;;
"-"*)
local complevel=$(echo $opt | sed 's/-//')
if ! [[ $complevel =~ ^[1-9]+$ ]]; then
disp E "Invalid option, use taz --help to display options list"
echo
return 1
fi
;;
*)
local LIST="$LIST ${opt%/}"
;;
-[1-9])
compression="${1#-}"
shift
;;
--)
shift
break
;;
*)
disp E "Invalid option, use \"taz --help\" to display options list"
return 1
;;
esac
done
# The remaining arguments after -- are the files/directories to process,
# "." is used if none is given
local FILES=("$@")
[[ ${#FILES[@]} -eq 0 ]] && FILES=(".")
[[ ! $compform ]] && compform=lz # safe and efficient (unless data are already compressed)
[[ ! $nproc ]] && nproc=1
[[ ! $complevel ]] && complevel=6
[[ $verbose -gt 1 && $QUIET -gt 1 ]] &&
disp E "The --verbose and --quiet options can't be used together."
[[ $verbose -gt 1 && $quiet -gt 1 ]] &&
disp E "The --verbose and --quiet options can't be used together."
for item in $LIST; do
for item in "${FILES[@]}"; do
local donetar=0
disp I "Processing $item..."
if [[ -d $item ]]; then
if [[ -d "$item" ]]; then
disp I "\t Creating $item.tar... "
tar -cf $item{.tar,}
tar -cf "$item.tar" "$item"
if [[ ! $? -eq 0 ]]; then
disp E "tar file creation failed, skipping to next item."
continue
@@ -336,26 +593,30 @@ taz ()
# Skip compression part if tar is asked
if [[ $compform != "tar" ]]; then
disp I "\t Compressing archive..."
_do$compform $fname $nproc $complevel $verbose
_do$compform "$fname" "$nproc" "$complevel" "$verbose"
[[ ! $? -eq 0 ]] && case $? in
127)
disp E "Compression program unavailable, aborting."
return 127
;;
*)
disp E "Compression program returned an error, not deleting anything if asked, skipping to next item."
continue
;;
127)
disp E "Compression program unavailable, aborting."
return 127
;;
*)
disp E "Compression program returned an error, not deleting anything if asked, skipping to next item."
continue
;;
esac
[[ $donetar -gt 0 ]] && rm $fname
[[ $donetar -gt 0 ]] && rm "$fname"
fi
if [[ $willrm ]]; then
disp I "\t Deleting original source as asked... "
rm -r $item
rm -r "$item"
fi
done
unset QUIET
unset quiet
}
export -f taz
# ------------------------------------------------------------------------------
# EOF

View File

@@ -1,5 +1,6 @@
#!/usr/bin/env bash
# ------------------------------------------------------------------------------
# Copyright (c) 2013-2022 Geoffray Levasseur <fatalerrors@geoffray-levasseur.org>
# Copyright (c) 2013-2026 Geoffray Levasseur <fatalerrors@geoffray-levasseur.org>
# Protected by the BSD3 license. Please read bellow for details.
#
# * Redistribution and use in source and binary forms,
@@ -35,73 +36,95 @@
# ------------------------------------------------------------------------------
# Display a backtrace
# ------------------------------------------------------------------------------
function backtrace ()
# Usage: backtrace
function backtrace()
{
echo "========= Call stack ========="
typeset -i i=0
local func=
for func in "${FUNCNAME[@]}"; do
if [[ $i -ne 0 ]]; then
printf '%15s() %s:%d\n' \
"$func" "${BASH_SOURCE[$i]}" "${BASH_LINENO[ (( $i - 1)) ]}"
fi
let i++ || true
printf "========= Call stack =========\n"
local i=1 # We begin at 1 to ignore backtrace itself
while [[ $i -lt ${#FUNCNAME[@]} ]]; do
printf '%15s() %s:%d\n' \
"${FUNCNAME[$i]}" "${BASH_SOURCE[$i]}" "${BASH_LINENO[$(( i-1 ))]}"
((i++))
done
unset func i
echo "=============================="
unset i
printf "==============================\n"
}
# ------------------------------------------------------------------------------
# Function to be trapped for errors investigation
# ------------------------------------------------------------------------------
function error ()
function error()
{
local errcode=$?
backtrace
return $errcode
}
# ------------------------------------------------------------------------------
# Activate or deactivate error trapping to display backtrace
# ------------------------------------------------------------------------------
settrace ()
# Usage: settrace <--on|--off|--status>
settrace()
{
local status="off"
[[ $(trap -p ERR) ]] && status="on"
#trap -p ERR
for opt in $@ ; do
case $opt in
"-h"|"--help")
echo "Try to activate backtrace display for script debugging."
echo
echo "Options:"
echo " --on Activate backtrace generation"
echo " --off Deactivate backtrace generation"
echo
echo "That function active a trap event on error. If the script you want to"
echo "debug overload the ERR bash trap, it will not work."
echo
;;
"--on")
if [[ $status == "on" ]]; then
disp W "ERR signal trap is already set, replacing previous trap!"
fi
trap "error" ERR
;;
"--off")
if [[ $status != "on" ]]; then
disp W "ERR signal trap is already unset!"
fi
trap - ERR
;;
"--status")
disp "ERR trap signal is ${status}."
;;
esac
local PARSED
PARSED=$(getopt -oh --long help,on,off,status,force -- "$@")
if [[ $? -ne 0 ]]; then
disp E "Invalid options, use \"settrace --help\" to display usage."
return 1
fi
eval set -- "$PARSED"
local force=0
while true; do
case $1 in
-h|--help)
printf "Try to activate backtrace display for script debugging.\n\n"
printf "Options:\n"
printf "\t--on\t\tActivate backtrace generation\n"
printf "\t--force\t\tForce replacement of existing trap (use with --on)\n"
printf "\t--off\t\tDeactivate backtrace generation\n\n"
printf "That function active a trap event on error. If the script you want to\n"
printf "debug overload the ERR bash trap, it will not work.\n"
return 0
;;
--on)
if [[ ${status} == "on" ]] && [[ $force -eq 0 ]]; then
disp E "ERR signal trap is already set. Use --force to replace it."
return 1
fi
trap "error" ERR
shift
;;
--force)
force=1
shift
;;
--off)
if [[ ${status} != "on" ]]; then
disp W "ERR signal trap is already unset!"
fi
trap - ERR
shift
;;
--status)
disp I "Trap signal is ${status}."
shift
;;
--)
shift
break
;;
*)
disp E "Invalid options, use \"settrace --help\" to display usage."
return 1
;;
esac
done
unset status
unset status force
}
export -f settrace
# ------------------------------------------------------------------------------
# EOF

View File

@@ -1,5 +1,6 @@
#!/usr/bin/env bash
# ------------------------------------------------------------------------------
# Copyright (c) 2013-2022 Geoffray Levasseur <fatalerrors@geoffray-levasseur.org>
# Copyright (c) 2013-2026 Geoffray Levasseur <fatalerrors@geoffray-levasseur.org>
# Protected by the BSD3 license. Please read bellow for details.
#
# * Redistribution and use in source and binary forms,
@@ -35,11 +36,11 @@
# ------------------------------------------------------------------------------
# Color definitions
# ------------------------------------------------------------------------------
# Standard 16 colors display declaration
export DEFAULTFG="\e[0;39m"
export DEFAULTBG="\e[0;49m"
export DEFAULTCOL=${DEFAULTBG}${DEFAULTFG}
export DEFAULTFG='\e[0;39m'
export DEFAULTBG='\e[0;49m'
export DEFAULTCOL="${DEFAULTBG}${DEFAULTFG}"
export RESETCOL=$'\e[0m'
# Regular Colors
export Black='\e[0;30m'
@@ -110,39 +111,73 @@ export On_IBlue='\e[0;104m'
export On_IPurple='\e[0;105m'
export On_ICyan='\e[0;106m'
export On_IWhite='\e[0;107m'
# ------------------------------------------------------------------------------
# ------------------------------------------------------------------------------
# Display a message
# ------------------------------------------------------------------------------
# Usage: disp <type> <message>
# Types:
# I : info (green)
# W : warning (yellow)
# E : error (red)
# D : debug (cyan)
disp()
{
case $1 in
"I")
# Handle NO_COLOR: disable colors if set
local color_enabled=1
[[ -n $NO_COLOR ]] && color_enabled=0
case ${1^^} in
"I")
if [[ $color_enabled -eq 1 ]]; then
local heads="[ ${IGreen}info${DEFAULTFG} ]"
shift
[[ -z $QUIET || $QUIET -ne 1 ]] && echo -e "${heads} $@"
;;
"W")
else
local heads="[ info ]"
fi
shift
[[ -z $QUIET || $QUIET -ne 1 ]] && \
printf "%b\n" "${heads} $*${RESETCOL}"
;;
"W")
if [[ $color_enabled -eq 1 ]]; then
local heads="[ ${IYellow}Warning${DEFAULTFG} ]"
shift
echo -e "${heads} $@" >&2
;;
"E")
else
local heads="[ Warning ]"
fi
shift
printf "%b\n" "${heads} $*${RESETCOL}" >&2
;;
"E")
if [[ $color_enabled -eq 1 ]]; then
local heads="[ ${IRed}ERROR${DEFAULTFG} ]"
shift
echo -e "${heads} $@" >&2
;;
"D")
local heads"[ ${ICyan}debug${DEFAULTFG} ]"
shift
[[ -n $DEBUG && $DEBUG -gt 1 ]] && echo -e "${heads} $@"
;;
"*")
local heads=""
[[ -z $QUIET || $QUIET -ne 1 ]] && echo -e "$@"
;;
else
local heads="[ ERROR ]"
fi
shift
printf "%b\n" "${heads} $*${RESETCOL}" >&2
;;
"D")
if [[ $color_enabled -eq 1 ]]; then
local heads="[ ${ICyan}debug${DEFAULTFG} ]"
else
local heads="[ debug ]"
fi
shift
[[ -n $DEBUG && $DEBUG -gt 1 ]] && \
printf "%b\n" "${heads} $*${RESETCOL}"
;;
* )
[[ -z $QUIET || $QUIET -ne 1 ]] && \
printf "%b\n" "$*"
;;
esac
unset heads
}
export -f disp
# ------------------------------------------------------------------------------
# Load disp section variables
load_conf disp
# EOF

View File

@@ -1,5 +1,6 @@
#!/usr/bin/env bash
# ------------------------------------------------------------------------------
# Copyright (c) 2013-2022 Geoffray Levasseur <fatalerrors@geoffray-levasseur.org>
# Copyright (c) 2013-2026 Geoffray Levasseur <fatalerrors@geoffray-levasseur.org>
# Protected by the BSD3 license. Please read bellow for details.
#
# * Redistribution and use in source and binary forms,
@@ -35,74 +36,98 @@
# ------------------------------------------------------------------------------
# expandlist : treat wildcards in a file/directory list
# ------------------------------------------------------------------------------
# Usage: expandlist <item1 [item2 ... itemN]>
expandlist()
{
if [[ "$1" == "-h" || "$1" == "--help" ]]; then
printf "expandlist: Wraps a list of items in double quotes.\n\n"
printf "Usage: expandlist <item1 [item2 ... itemN]>\n\n"
printf "Options:\n"
printf "\t-h, --help\t\tDisplay this help screen\n"
return 0
fi
local result=""
for item in "$1"; do
for item in "$@"; do
for content in "$item"; do
result+="\"$content\" "
done
done
echo $result
}
export -f expandlist
# ------------------------------------------------------------------------------
# ------------------------------------------------------------------------------
# Clean a directory or a tree from temporary or backup files
# ------------------------------------------------------------------------------
clean ()
# Usage: clean [options] [directory1] [...[directoryX]]
# Options:
# -h, --help: display help screen
# -r, --recurs: do a recursive cleaning
# -f, --force: do not ask for confirmation (use with care)
# -s, --shell: do nothing and display what will be executed
clean()
{
for opt in $@ ; do
case $opt in
"-r"|"--recurs")
local recursive=1
;;
local recursive=0 force=0 outshell=0
"-h"|"--help")
echo "clean: erase backup files in the given directories."
echo
echo "Usage: clean [option] [directory1] [...[directoryX]]"
echo
echo "Options:"
echo " -h, --help Display that help screen"
echo " -r, --recurs Do a recursive cleaning"
echo " -f, --force Do not ask for confirmation (use with care)"
echo " -s, --shell Do nothing and display what will be executed"
echo
# Define short and long options
local PARSED
PARSED=$(getopt -o hrsf --long help,recurs,shell,force -n 'clean' -- "$@")
if [[ $? -ne 0 ]]; then
disp E "Invalid options, use \"clean --help\" to display usage."
return 1
fi
eval set -- "$PARSED"
while true; do
case "$1" in
-r|--recurs)
local recursive=1
shift
;;
-h|--help)
printf "clean: erase backup files in the given directories.\n\n"
printf "Usage: clean [option] [directory1] [...[directoryX]]\n"
printf "Options:\n"
printf "\t-h, --help\t\tDisplay that help screen\n"
printf "\t-r, --recurs\t\tDo a recursive cleaning\n"
printf "\t-f, --force\t\tDo not ask for confirmation (use with care)\n"
printf "\t-s, --shell\t\tDo nothing and display what will be executed\n"
printf "\n"
return 0
;;
"-s"|"--shell")
-s|--shell)
local outshell=1
shift
;;
"-f"|"--force")
-f|--force)
local force=1
shift
;;
"-"*)
disp E "Invalid option, use \"clean --help\" to display usage."
echo
return 1
--)
shift
break
;;
*)
local dirlist="$dirlist $opt"
;;
disp E "Invalid parameter, use \"clean --help\" to display options list"
return 1
esac
done
[[ ! $dirlist ]] && local dirlist=$(pwd)
# Handle remaining arguments as directories
local dirlist=("$@")
[[ ${#dirlist[@]} -eq 0 ]] && dirlist=(".")
[[ ! $recursive ]] && local findopt="-maxdepth 1"
[[ ! $force ]] && local rmopt="-i"
local findopt=() rmopt
[[ ! $recursive ]] && findopt=(-maxdepth 1)
[[ ! $force ]] && rmopt="-i"
unset recursive force
for dir in $dirlist; do
local dellist=$(find $dir $findopt -type f -name "*~" -o -name "#*#" \
-o -name "*.bak" -o -name ".~*#")
for f in $dellist; do
find "$dir" "${findopt[@]}" -type f \( -name "*~" -o -name "#*#" -o -name "*.bak" -o -name ".~*#" \) -print0 | while IFS= read -r -d '' f; do
if [[ ! $outshell ]]; then
rm $rmopt $f
else
@@ -113,69 +138,98 @@ clean ()
unset outshell dirlist dellist findopt rmopt
}
export -f clean
# ------------------------------------------------------------------------------
# ------------------------------------------------------------------------------
# Create a directory then goes inside
# ------------------------------------------------------------------------------
mcd ()
# Usage: mcd <directory>
mcd()
{
if [[ ! $# -eq 1 ]] ; then
disp E "Create a directory then goes inside."
disp E "Usage: mcd <directory>"
if [[ "$1" == "-h" || "$1" == "--help" ]]; then
printf "mcd: Create a directory and enter it.\n\n"
printf "Usage: mcd <directory>\n"
printf "Options:\n"
printf "\t-h, --help\t\tDisplay this help screen\n"
return 0
fi
if [[ ! $# -eq 1 ]]; then
disp E "Missing parameter. Use \"mcd --help\" to display usage."
return 1
fi
mkdir -pv $1 && cd $1
mkdir -pv "$1" && cd "$1" || {
printf "Failed create and/or change directory.\n"
return 1
}
}
export -f mcd
# ------------------------------------------------------------------------------
# ------------------------------------------------------------------------------
# Rename all files in current directory to replace spaces with _
# ------------------------------------------------------------------------------
rmspc ()
# Usage: rmspc [options]
# Options:
# -h, --help: display help screen
# -r, --recursive: treat subdirectories of the given directory
# -c, --subst-char: change the replacement character (default is underscore)
# -v, --verbose: display more details (recursive mode only)
# -s, --shell: do nothing and display commands that would be executed
rmspc()
{
local lst=""
for opt in $@ ; do
case $opt in
"-h"|"--help")
echo "rmspc: remove spaces from all filenames in current directories"
echo
echo "Usage: rmspc [option]"
echo
echo "Options:"
echo " -h, --help Display that help screen"
echo " -r, --recursive Treat subdirectories of the given directory"
echo " -c, --subst-char Change the replacement character (default is underscore)"
echo " -v, --verbose Display more details (recursive mode only)"
echo " -s, --shell Do nothing and display commands that would be executed"
echo
echo "Note: if the --subst-char option is given without parameters, spaces will be"
echo " replaced with nothing (concatenation)."
echo
return 0
;;
local PARSED
PARSED=$(getopt -o hr:c::vs --long help,recursive,subst-char::,verbose,shell -n 'rmspc' -- "$@")
if [[ $? -ne 0 ]]; then
disp E "Invalid options, use \"rmspc --help\" to display usage."
return 1
fi
eval set -- "$PARSED"
"-r"|"--recursive")
while true; do
case "$1" in
-h|--help)
printf "rmspc: remove spaces from all filenames in current directories\n\n"
printf "Usage: rmspc [option]\n\n"
printf "Options:\n"
printf "\t-h, --help\t\tDisplay that help screen\n"
printf "\t-r, --recursive\t\tTreat subdirectories of the given directory\n"
printf "\t-c, --subst-char\tChange the replacement character (default is underscore)\n"
printf "\t-v, --verbose\t\tDisplay more details (recursive mode only)\n"
printf "\t-s, --shell\t\tDo nothing and display commands that would be executed\n\n"
printf "Note: if the --subst-char option is given without parameters, spaces will be\n"
printf " replaced with nothing (concatenation).\n"
return 0
;;
-r|--recursive)
local recurs=1
shift
;;
"-c"?*|"--subst-char"?*)
if [[ $(echo $opt | grep "=") ]]; then
local substchar=$(echo "$opt" | cut -f 2- -d '=')
else
local substchar='none'
fi
;;
"-v"|"--verbose")
local verb=1
-c|--subst-char)
# Handle optional argument for short/long options
case "$2" in
"")
substchar=""
;;
*)
substchar="$2"
;;
esac
shift 2
;;
"-s"|"--shell")
-v|--verbose)
local verb=1
shift
;;
-s|--shell)
local shell=1
shift
;;
--)
shift
break
;;
*)
disp E "Invalid parameter, use \"rmspc --help\" to display options list"
echo
@@ -188,27 +242,485 @@ rmspc ()
[[ $substchar == "none" ]] && local substchar=""
[[ $verb ]] && local mvopt="-v"
shopt -s nullglob
for f in *; do
[[ $recurs ]] && [[ -d "$f" ]] && (
[[ $verb ]] && disp I "Entering directory $(pwd)/$f ..."
local lastdir=$f
pushd "$f" > /dev/null
rmspc $@
popd > /dev/null
local lastdir=$f
pushd "$f" >/dev/null
rmspc ${recurs:+-r} ${substchar:+-c "$substchar"} ${verb:+-v} ${shell:+-s}
popd >/dev/null
[[ $verb ]] && disp I "Leaving directory $(pwd)/$lastdir"
unset lastdir
unset lastdir
)
if [[ $(echo $f | grep " ") ]]; then
if [[ "$f" == *" "* ]]; then
local newf="${f// /${substchar}}"
local command="mv $mvopt \"$f\" \"$newf\""
if [[ $shell ]]; then
echo $command
[[ "$f" == "$newf" ]] && continue # protection but should never happen
if [[ -n $shell ]]; then
echo "mv ${mvopt:+$mvopt }\"$f\" \"$newf\""
else
$command
mv ${mvopt:+$mvopt} "$f" "$newf" || {
disp E "Failed renaming \"$f\" to \"$newf\"."
continue
}
fi
fi
done
unset lst substchar verb shell newf command mvopt
}
export -f rmspc
# ------------------------------------------------------------------------------
# ------------------------------------------------------------------------------
# display stats about a file structure
# Usage: file_stats [options] [path]
# Options:
# -H, --human Human readable sizes\n"
# -d, --details Display details (min/max/average/median)
# -m, --average Display only average size
# -M, --median Display only median size
# -c, --count Display only count of files
# -t, --total Display only total size
# -a, --all Display all stats in human readable format (shortcut for -H -d)
# -x, --ext [ext] Filter by extension (e.g. -x log for .log files)
# -X, --ext-list [list] Filter by multiple extensions (e.g. -X log,txt)
# --min [size] Minimum size (e.g., 10M)
# --max [size] Maximum size (e.g., 100M)
file_stats()
{
local human=0 details=0 only_avg=0 only_med=0 only_count=0 only_total=0
local path="." show_all=1 ext_filter="" ext_list="" min_size="" max_size=""
local PARSED
# Short: H, d, m, M, c, t, a, x:, X:
# Long: human, details, average, median, count, total, all, ext:, ext-list:, min:, max:, help
PARSED=$(getopt -o HdmMctax:X:h --long human,details,average,median,count,total,all,ext:,ext-list:,min:,max:,help -n 'file_stats' -- "$@")
if [[ $? -ne 0 ]]; then
disp E "Invalid options, use \"file_stats --help\" to display usage."
return 1
fi
eval set -- "$PARSED"
while true; do
case "$1" in
-h|--help)
printf "Usage: file_stats [options] [path]\n\n"
printf "Options:\n"
printf "\t-H, --human\t\tHuman readable sizes\n"
printf "\t-d, --details\t\tShow detailed histogram\n"
printf "\t-m, --average\t\tShow only average size\n"
printf "\t-M, --median\t\tShow only median size\n"
printf "\t-c, --count\t\tShow only file count\n"
printf "\t-t, --total\t\tShow only total size\n"
printf "\t-a, --all\t\tShow all (human + details)\n"
printf "\t-x, --ext [ext]\t\tFilter by extension\n"
printf "\t-X, --ext-list [list]\tFilter by comma-separated list\n"
printf "\t--min [size]\t\tMinimum size (e.g., 10M)\n"
printf "\t--max [size]\t\tMaximum size (e.g., 100M)\n"
return 0 ;;
-H|--human)
human=1
shift
;;
-d|--details)
details=1
shift
;;
-m|--average)
only_avg=1
show_all=0
shift
;;
-M|--median)
only_med=1
show_all=0
shift
;;
-c|--count)
only_count=1
show_all=0
shift
;;
-t|--total)
only_total=1
show_all=0
shift
;;
-a|--all)
human=1
details=1
shift
;;
-x|--ext)
ext_filter="${2#.}"
shift 2
;;
-X|--ext-list)
ext_list="$2"
shift 2
;;
--min)
min_size="$2"
shift 2
;;
--max)
max_size="$2"
shift 2
;;
--)
shift
break
;;
*)
disp E "Invalid option: $1"
return 1
;;
esac
shift
done
[[ -n "$1" ]] && path="$1"
# Prepare find filters
local find_cmd=(find "$path" -type f)
# Extension simple
if [[ -n "$ext_filter" ]]; then
find_cmd+=(-iname "*.$ext_filter")
fi
# Extension liste
if [[ -n "$ext_list" ]]; then
IFS=',' read -ra exts <<< "$ext_list"
find_cmd+=('(')
for i in "${!exts[@]}"; do
[[ $i -ne 0 ]] && find_cmd+=(-o)
find_cmd+=(-iname "*.${exts[$i]}")
done
find_cmd+=(')')
fi
# Taille min/max (à évaluer en octets)
if [[ -n "$min_size" ]]; then
find_cmd+=(-size +"$(numfmt --from=iec "$min_size")"c)
fi
if [[ -n "$max_size" ]]; then
find_cmd+=(-size -"$(( $(numfmt --from=iec "$max_size") + 1 ))"c)
fi
# Exécution
"${find_cmd[@]}" -printf "%s\n" 2>/dev/null | sort -n | \
awk -v human="$human" -v details="$details" -v only_avg="$only_avg" \
-v only_med="$only_med" -v only_count="$only_count" \
-v only_total="$only_total" -v show_all="$show_all" -v path="$path" '
# Convert function
function human_readable(x) {
split("B KiB MiB GiB TiB", units)
i = 1
while (x >= 1024 && i < 5) {
x /= 1024
i++
}
return sprintf("%.2f %s", x, units[i])
}
# Display function
function out(label, val, is_size) {
if (human == 1 && is_size == 1) val = human_readable(val)
printf "%-20s : %s\n", label, val
}
{
sizes[NR] = $1
total += $1
if (min == "" || $1 < min) min = $1
if (max == "" || $1 > max) max = $1
if ($1 == 0) bucket[0]++
else {
b = int(log($1)/log(1024))
bucket[b]++
}
}
END {
count = NR
if (count == 0) {
print "No files found."
exit
}
average = total / count
# Median calculation: exact using sorted array values
if (count % 2 == 1) {
median = sizes[(count + 1) / 2]
} else {
idx = count / 2
median = (sizes[idx] + sizes[idx + 1]) / 2
}
if (only_avg) out("Average size", average, 1)
else if (only_med) out("Median size", median, 1)
else if (only_count) out("Number of files", count, 0)
else if (only_total) out("Total size", total, 1)
else {
if (show_all || human || details) {
printf "Statistics for \"%s\"\n", path
printf "-------------------------\n"
}
out("Number of files", count, 0)
out("Total size", total, 1)
out("Average size", average, 1)
out("Median size", median, 1)
out("Minimum size", min, 1)
out("Maximum size", max, 1)
}
if (details) {
print "\nSize histogram:"
# Use a separate array for the loop to avoid collision
for (b in bucket) {
# Pre-calculate label parts
# 1024^0 = 1 (B), 1024^1 = 1K, etc.
low = (b == 0) ? 0 : (1024^b)
high = 1024^(b+1)
label = sprintf("%-9s %-9s",
(b == 0) ? "0" : human_readable(low),
human_readable(high))
# We store buckets in an array, access them by index b
printf "%-25s : %6d fichiers\n", label, bucket[b]
}
}
}'
}
export -f file_stats
# ------------------------------------------------------------------------------
# ------------------------------------------------------------------------------
# Find the biggest files in a directory tree
# Usage: findbig [options] [directory]
# Options:
# -h : display help screen
# -d : display details (ls -l) for each file
# -x : do not cross filesystem boundaries
# -l : limit : number of files to return (default is 10)
findbig()
{
local details=0 limit=10 no_change=0 one_fs=0
local PARSED
PARSED=$(getopt -o hd:l:x --long help,details,one-fs,limit: -n 'findbig' -- "$@")
if [[ $? -ne 0 ]]; then
disp E "Invalid options, use \"findbig --help\" to display usage."
return 1
fi
eval set -- "$PARSED"
while true; do
case "$1" in
-h|--help)
printf "findbig: Find the N biggest files in a directory tree.\n\n"
printf "Usage: findbig [options] [directory]\n\n"
printf "Options:\n"
printf "\t-h, --help\t\tDisplay this help screen\n"
printf "\t-d, --details\t\tShow detailed file info (ls -ld)\n"
printf "\t-l, --limit N\t\tNumber of files to return (default: 10)\n"
printf "\t-x, --one-fs\t\tDo not cross filesystem boundaries\n"
return 0
;;
-d|--details)
details=1
shift
;;
-n|--no-change)
no_change=1
shift
;;
-l|--limit)
limit="$2"
shift 2
;;
--)
shift
break
;;
*)
disp E "Invalid option: $1"
return 1
;;
esac
done
local dir="${1:-.}"
# Prepare find arguments in an array for cleaner handling
local find_args=("-L" "$dir" "-type" "f")
(( one_fs )) && find_args+=("-xdev")
# Logic: find files, print size and path, sort numeric reverse, take N
if (( details )); then
find "${find_args[@]}" -printf "%s %p\n" 2>/dev/null | sort -rn | head -n "$limit" | while read -r size path; do
ls -ld "$path"
done
else
find "${find_args[@]}" -printf "%s %p\n" 2>/dev/null | sort -rn | head -n "$limit"
fi
}
export -f findbig
# ------------------------------------------------------------------------------
# ------------------------------------------------------------------------------
# Find empty files in a directory tree
# Usage: findzero [options] [directory]
# Options:
# -h : display help screen
# -d : display details (ls -l) for each file
# -x : do not cross filesystem boundaries
# --delete : delete empty files and display their paths
findzero()
{
local delete=0 details=0 one_fs=0 no_change=0
local PARSED
# o: options, long: long equivalents
PARSED=$(getopt -o hdx --long help,details,one-fs,delete -n 'findzero' -- "$@")
if [[ $? -ne 0 ]]; then
disp E "Invalid options, use \"findzero --help\" to display usage."
return 1
fi
eval set -- "$PARSED"
while true; do
case "$1" in
-h|--help)
printf "findzero: Find or delete empty files in a directory tree.\n\n"
printf "Usage: findzero [options] [directory]\n\n"
printf "Options:\n"
printf "\t-h, --help\t\tDisplay this help screen\n"
printf "\t-d, --details\t\tShow detailed file info (ls -ls)\n"
printf "\t-x, --one-fs\t\tDo not cross filesystem boundaries\n"
printf "\t--delete\t\tActually remove the empty files\n"
return 0 ;;
-d|--details)
details=1
shift
;;
-x|--one-fs)
one_fs=1
shift
;;
--delete)
delete=1
shift
;;
--)
shift
break
;;
*)
disp E "Invalid option: $1"
return 1
;;
esac
done
local dir="${1:-.}"
local find_args=("-L" "$dir" "-type" "f" "-empty")
(( one_fs )) && find_args+=("-xdev")
# Execution logic
if (( delete )); then
disp W "Deleting empty files in $dir..."
find "${find_args[@]}" -delete -print
elif (( details )); then
find "${find_args[@]}" -ls
else
find "${find_args[@]}"
fi
}
export -f findzero
# ------------------------------------------------------------------------------
# ------------------------------------------------------------------------------
# Find dead symbolic links in a directory tree
# Usage: finddead [options] [directory]
# Options:
# -h : display help screen
# -d : display details (ls -l) for each link
# -x : do not cross filesystem boundaries
# --delete : delete dead links and display their paths
finddead()
{
local delete=0 details=0 one_fs=0 no_change=0
local PARSED
PARSED=$(getopt -o hdx --long help,details,one-fs,delete -n 'finddead' -- "$@")
if [[ $? -ne 0 ]]; then
disp E "Invalid options, use \"finddead --help\" to display usage."
return 1
fi
eval set -- "$PARSED"
while true; do
case "$1" in
-h|--help)
printf "finddead: Find or delete dead/broken symbolic links.\n\n"
printf "Usage: finddead [options] [directory]\n\n"
printf "Options:\n"
printf "\t-h, --help\t\tDisplay this help screen\n"
printf "\t-d, --details\t\tShow detailed symlink info (ls -ls)\n"
printf "\t-x, --one-fs\t\tDo not cross filesystem boundaries\n"
printf "\t--delete\t\tActually remove the dead links\n"
return 0 ;;
-d|--details)
details=1
shift
;;
-x|--one-fs)
one_fs=1
shift
;;
--delete)
delete=1
shift
;;
--)
shift
break
;;
*)
disp E "Invalid option: $1"
return 1
;;
esac
done
local dir="${1:-.}"
# -xtype l searches for links that do not point to an existing file
local find_args=("$dir" "-xtype" "l")
(( one_fs )) && find_args+=("-xdev")
# Execution logic
if (( delete )); then
disp W "Deleting dead symlinks in $dir..."
find "${find_args[@]}" -delete -print
elif (( details )); then
find "${find_args[@]}" -ls
else
find "${find_args[@]}"
fi
}
export -f finddead
# ------------------------------------------------------------------------------
# EOF

View File

@@ -1,5 +1,6 @@
#!/usr/bin/env bash
# ------------------------------------------------------------------------------
# Copyright (c) 2013-2022 Geoffray Levasseur <fatalerrors@geoffray-levasseur.org>
# Copyright (c) 2013-2026 Geoffray Levasseur <fatalerrors@geoffray-levasseur.org>
# Protected by the BSD3 license. Please read bellow for details.
#
# * Redistribution and use in source and binary forms,
@@ -35,14 +36,73 @@
# ------------------------------------------------------------------------------
# Make non-IT peoples think you're busy doing something hard
# ------------------------------------------------------------------------------
# Usage: busy [options] [pattern]
# Options:
# --delay=<ms> : add a delay between each line output (milliseconds)
# pattern : the string to search for in the hexdump output (default is "ca fe")
busy()
{
if [[ -n $1 ]]; then
local pattern="$@"
else
local pattern="ca fe"
local pattern="ca fe" delay_ms=0
local PARSED
# Short: h, p:, d:
# Long: help, pattern:, delay:
PARSED=$(getopt -o hp:d: --long help,pattern:,delay: -n 'busy' -- "$@")
if [[ $? -ne 0 ]]; then
disp E "Invalid options, use \"busy --help\" to display usage."
return 1
fi
cat /dev/urandom | hexdump -C | grep "$pattern"
unset pattern
eval set -- "$PARSED"
while true; do
case "$1" in
-h|--help)
printf "busy: Monitor /dev/urandom for a specific pattern.\n\n"
printf "Usage: busy [options] [pattern]\n\n"
printf "Options:\n"
printf "\t-h, --help\t\tDisplay this help screen\n"
printf "\t-p, --pattern PATTERN\tHex pattern to search (default: \"ca fe\")\n"
printf "\t-d, --delay MS\t\tDelay between matches in milliseconds\n"
return 0
;;
-p|--pattern)
pattern="$2"
shift 2
;;
-d|--delay)
delay_ms="$2"
if ! [[ "$delay_ms" =~ ^[0-9]+$ ]]; then
disp E "Invalid delay: must be an integer (milliseconds)."
return 1
fi
shift 2
;;
--)
shift
break
;;
*)
disp E "Invalid option: $1"
return 1
;;
esac
done
# If a pattern was provided as a positional argument (e.g., 'busy "ff 00"'),
# it is captured here.
[[ -n "$1" ]] && pattern="$1"
# Convert milliseconds to seconds for 'sleep'
local delay_s=$(awk "BEGIN { printf \"%.3f\", $delay_ms / 1000 }")
# Monitor /dev/urandom
cat /dev/urandom | hexdump -C | grep --line-buffered "$pattern" | \
while read -r line; do
echo "$line"
[[ $delay_ms -gt 0 ]] && sleep "$delay_s"
done
}
# ------------------------------------------------------------------------------
# EOF

View File

@@ -1,5 +1,6 @@
#!/usr/bin/env bash
# ------------------------------------------------------------------------------
# Copyright (c) 2013-2022 Geoffray Levasseur <fatalerrors@geoffray-levasseur.org>
# Copyright (c) 2013-2026 Geoffray Levasseur <fatalerrors@geoffray-levasseur.org>
# Protected by the BSD3 license. Please read bellow for details.
#
# * Redistribution and use in source and binary forms,
@@ -35,34 +36,43 @@
# ------------------------------------------------------------------------------
# Display list of commands and general informations
# ------------------------------------------------------------------------------
# Usage: help
help()
{
cat <<EOF
clean Erase backup files
dpkgs Search for the given package in the installed ones
gpid Give the list of PIDs for the given process name
isipv4 Tell if the given IPv4 is valid
isipv6 Tell if the given IPv6 is valid
ku Kill process owned by users in parameter
mcd Create a directory and go inside
meteo Display curent weather forecast for the configured city
ppg Display process matching the given parameter
rain Let the rain fall
rmhost Remove host (IP and/or DNS name) for current known_host
rmspc Remove spaces from all the files in working directory
setc Set console language to C
setfr Set console language to French
settrace Activate/deactivate call trace for script debugging
setus Set console language to US English
showinfo Show the welcoming baner with basic system information
ssr Do a root login to the given address
taz Compress smartly the given files or directory
utaz Uncompress all zip files in the given (or current) directory
ver Display version of your copy of profile
printf "check_updates\tCheck for profile updates\n"
printf "clean\t\tErase backup files\n"
printf "dpkgs\t\tSearch for the given package in the installed ones\n"
printf "findbig\t\tFind big files in the given (or current) directory\n"
printf "findempty\tFind empty files and directories in the given (or current) directory\n"
printf "finddead\tFind dead symbolic links in the given (or current) directory\n"
printf "gpid\t\tGive the list of PIDs for the given process name\n"
printf "isipv4\t\tTell if the given IPv4 is valid\n"
printf "isipv6\t\tTell if the given IPv6 is valid\n"
printf "ku\t\tKill process owned by users in parameter\n"
printf "mcd\t\tCreate a directory and go inside\n"
printf "meteo\t\tDisplay curent weather forecast for the configured city\n"
printf "ppg\t\tDisplay process matching the given parameter\n"
printf "ppn\t\tDisplay process matching the exact process name given in parameter\n"
printf "ppu\t\tDisplay processes owned by the given user\n"
printf "profile_update\tUpdate profile to the latest version\n"
printf "rain\t\tLet the rain fall\n"
printf "rmhost\t\tRemove host (IP and/or DNS name) for current known_host\n"
printf "rmspc\t\tRemove spaces from all the files in working directory\n"
printf "setlocale\tSet console language to the current locale\n"
printf " * setc\tSet console language to C\n"
printf " * setfr\tSet console language to French\n"
printf " * setus\tSet console language to US English\n"
printf "settrace\tActivate/deactivate call trace for script debugging\n"
printf "showinfo\tShow the welcoming baner with basic system information\n"
printf "ssr\t\tDo a root login to the given address\n"
printf "taz\t\tCompress smartly the given files or directory\n"
printf "utaz\t\tUncompress all zip files in the given (or current) directory\n"
printf "ver\t\tDisplay version of your copy of profile\n\n"
Please use <command> --help to obtain usage details.
EOF
printf "\nPlease use <command> --help to obtain usage details.\n"
}
export -f help
# ------------------------------------------------------------------------------
# EOF

View File

@@ -1,5 +1,6 @@
#!/usr/bin/env bash
# ------------------------------------------------------------------------------
# Copyright (c) 2013-2022 Geoffray Levasseur <fatalerrors@geoffray-levasseur.org>
# Copyright (c) 2013-2026 Geoffray Levasseur <fatalerrors@geoffray-levasseur.org>
# Protected by the BSD3 license. Please read bellow for details.
#
# * Redistribution and use in source and binary forms,
@@ -35,56 +36,144 @@
# ------------------------------------------------------------------------------
# Show profile version
# ------------------------------------------------------------------------------
ver ()
# Usage: ver
ver()
{
local PARSED=$(getopt -o h --long help -n 'ver' -- "$@")
if [[ $? -ne 0 ]]; then
disp E "Invalid options, use \"ver --help\" to display usage."
return 1
fi
eval set -- "$PARSED"
while true; do
case "$1" in
-h|--help)
printf "ver: Display the current profile version.\nUsage: ver\n"
return 0
;;
--)
shift
break
;;
*)
disp E "Invalid options, use \"ver --help\" to display usage."
return 1
;;
esac
done
[[ -z $PROFVERSION ]] && \
disp W "No version defined. Profile is probably badly installed." && \
return 1
disp "Profile version $PROFVERSION."
}
export -f ver
# ------------------------------------------------------------------------------
# ------------------------------------------------------------------------------
# Display weather of the given city (or default one)
# ------------------------------------------------------------------------------
meteo ()
# Usage: meteo [city1 city2 ...]
meteo()
{
cities=$@
[[ $# -eq 0 ]] && local cities=$DEFAULT_CITY
local PARSED=$(getopt -o h --long help -n 'meteo' -- "$@")
if [[ $? -ne 0 ]]; then
disp E "Invalid options, use \"meteo --help\" to display usage."
return 1
fi
eval set -- "$PARSED"
while true; do
case "$1" in
-h|--help)
printf "meteo: Fetch weather data.\nUsage: meteo [city1 city2 ...]\n"
return 0
;;
--)
shift
break
;;
*)
disp E "Invalid options, use \"meteo --help\" to display usage."
return 1
;;
esac
done
for city in $cities; do
curl https://wttr.in/$city || disp E "Failed fetching datas for $city."
local cities=("$@")
[[ $# -eq 0 ]] && cities=("$DEFAULT_CITY")
for city in "${cities[@]}"; do
encoded=$(urlencode "$city")
dwl "https://wttr.in/$encoded" || \
disp E "Failed fetching datas for $city."
done
}
export -f meteo
# ------------------------------------------------------------------------------
# ------------------------------------------------------------------------------
# Display system general information
# ------------------------------------------------------------------------------
# Usage: showinfo
showinfo()
{
echo -e "\n"
local PARSED=$(getopt -o h --long help -n 'showinfo' -- "$@")
if [[ $? -ne 0 ]]; then
disp E "Invalid options, use \"showinfo --help\" to display usage."
return 1
fi
eval set -- "$PARSED"
while true; do
case "$1" in
-h|--help)
printf "showinfo: Display system information (hostname, kernel, uptime).\nUsage: showinfo\n"
return 0
;;
--)
shift
break
;;
*)
disp E "Invalid options, use \"showinfo --help\" to display usage."
return 1
;;
esac
done
printf "\n"
if command -v figlet >/dev/null 2>&1; then
if [[ -s /usr/share/figlet/ansi_shadow.flf ]]; then
local figopt="-f ansi_shadow"
fi
figlet -k $(hostname) $figopt
if [[ -s /usr/share/figlet/ansi_shadow.flf ]]; then
local figopt="-f ansi_shadow"
fi
if [[ -n $figopt ]]; then
figlet -k $figopt $(hostname)
else
figlet $(hostname)
fi
else
echo "$(hostname -f)"
hostname -f
fi
echo ""
if command -v neofetch >/dev/null 2>&1; then
neofetch
neofetch
elif command -v fastfetch >/dev/null 2>&1; then
fastfetch
else
(
if [[ -s /etc/os-release ]]; then
. /etc/os-release
echo "$NAME $VERSION"
else
cat /proc/version
fi
echo "Uptime: $(uptime)"
)
(
if [[ -s /etc/os-release ]]; then
# shellcheck disable=SC1091
. /etc/os-release
printf "$NAME $VERSION\n"
else
cat /proc/version
fi
printf "Uptime: $(uptime -p)\n"
)
fi
}
export -f showinfo
# ------------------------------------------------------------------------------
load_conf info
# EOF

View File

@@ -1,5 +1,6 @@
#!/usr/bin/env bash
# ------------------------------------------------------------------------------
# Copyright (c) 2013-2022 Geoffray Levasseur <fatalerrors@geoffray-levasseur.org>
# Copyright (c) 2013-2026 Geoffray Levasseur <fatalerrors@geoffray-levasseur.org>
# Protected by the BSD3 license. Please read bellow for details.
#
# * Redistribution and use in source and binary forms,
@@ -33,38 +34,102 @@
# * OF SUCH DAMAGE.
# ------------------------------------------------------------------------------
# ------------------------------------------------------------------------------
# Change locale to French
# ------------------------------------------------------------------------------
setfr ()
locale_check()
{
# Set fr locale definitions
export LANG=fr_FR.UTF-8
export LC_MESSAGES=fr_FR.UTF-8
export LC_ALL=fr_FR.UTF-8
locale -a | grep -qx "$1" || {
disp W "Locale '$1' is not installed on this system."
return 1
}
return 0
}
export -f setfr
# ------------------------------------------------------------------------------
# Change locale to C standard
# Change locale to the given one in parameter
# Usage: setlocale <locale>
setlocale()
{
local PARSED
PARSED=$(getopt -o h --long help -n 'setlocale' -- "$@")
if [[ $? -ne 0 ]]; then
disp E "Invalid options, use \"setlocale --help\" to display usage."
return 1
fi
eval set -- "$PARSED"
while true; do
case "$1" in
-h|--help)
printf "setlocale: Configure system environment locale variables.\n\n"
printf "Usage: setlocale <locale>\n\n"
printf "Options:\n"
printf " -h, --help Display this help screen\n"
return 0
;;
--)
shift
break
;;
*)
disp E "Invalid options, use \"setlocale --help\" to display usage."
return 1
;;
esac
done
local loc=$1
[[ -z $loc ]] && disp E "No locale specified." && return 1
locale_check "$loc" || return 1
export LANG=$loc
export LC_MESSAGES=$loc
export LC_TIME=$loc
export LC_NUMERIC=$loc
export LC_MONETARY=$loc
export LC_COLLATE=$loc
export LC_CTYPE=$loc
disp I "Locale set to $loc."
}
export -f setlocale
# ------------------------------------------------------------------------------
setc ()
# ------------------------------------------------------------------------------
# Special case : change locale to C standard
# Usage: setc
setc()
{
# Locale definitions
export LANG=C
export LC_MESSAGES=C
export LC_ALL=C
disp I "Locale changed to standard C (POSIX)."
}
export -f setc
# ------------------------------------------------------------------------------
# ------------------------------------------------------------------------------
# Change locale to French
# Usage: setfr
setfr()
{
# Set fr locale definitions
setlocale "fr_FR.UTF-8"
}
export -f setfr
# ------------------------------------------------------------------------------
# ------------------------------------------------------------------------------
# Change locale to US (needed by Steam)
# ------------------------------------------------------------------------------
setus ()
# Usage: setus
setus()
{
# Locale definitions
export LANG=en_US.UTF-8
export LC_MESSAGES=en_US.UTF-8
export LC_ALL=en_US.UTF-8
setlocale "en_US.UTF-8"
}
export -f setus
# ------------------------------------------------------------------------------
# ------------------------------------------------------------------------------
# EOF

View File

@@ -1,5 +1,6 @@
#!/usr/bin/env bash
# ------------------------------------------------------------------------------
# Copyright (c) 2013-2022 Geoffray Levasseur <fatalerrors@geoffray-levasseur.org>
# Copyright (c) 2013-2026 Geoffray Levasseur <fatalerrors@geoffray-levasseur.org>
# Protected by the BSD3 license. Please read bellow for details.
#
# * Redistribution and use in source and binary forms,
@@ -34,51 +35,238 @@
# ------------------------------------------------------------------------------
# ------------------------------------------------------------------------------
# Determine if parameter is a valid IPv4 address
# Download a resource using curl, wget, or fetch.
# Usage: dwl <url> [output_file]
dwl()
{
case "$1" in
--help|-h)
echo "Usage: dwl <url> [output_file]"
echo "Downloads a resource using curl, wget, or fetch."
echo ""
echo "Arguments:"
echo " url The full URL to download (http/https/ftp)."
echo " output_file (Optional) Path to save the file. If omitted, prints to stdout."
return 0
;;
"")
echo "Error: URL argument is missing." >&2
echo "Try 'get_resource --help' for usage." >&2
return 1
;;
esac
case "$1" in
http://*|https://*|ftp://*) ;;
*)
echo "Error: '$1' does not look like a valid URL. Must start with http://, https://, or ftp://" >&2
return 1
;;
esac
local url="$1"
local output="$2"
if command -v curl >/dev/null 2>&1; then
[ -z "$output" ] && curl -sL "$url" || curl -sL -o "$output" "$url"
elif command -v wget >/dev/null 2>&1; then
[ -z "$output" ] && wget -qO- "$url" || wget -q -O "$output" "$url"
elif command -v fetch >/dev/null 2>&1; then
[ -z "$output" ] && fetch -o - "$url" || fetch -o "$output" "$url"
else
echo "Error: No download utility (curl, wget, or fetch) found." >&2
return 1
fi
}
export -f dwl
# ------------------------------------------------------------------------------
isipv4 ()
# ------------------------------------------------------------------------------
# Determine if parameter is a valid IPv4 address
# Usage: isipv4 <ip_address>
isipv4()
{
# Set up local variables
local ip=$1
local ip=$1
[[ -z $ip ]] && return 1
# Start with a regex format test
if [[ $ip =~ ^[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}$ ]]; then
local old_ifs=$IFS
IFS="."
ip=($ip)
IFS=$old_ifs
if [[ ${ip[0]} -le 255 && ${ip[1]} -le 255 \
&& ${ip[2]} -le 255 && ${ip[3]} -le 255 ]]; then
if [[ -t 1 ]]; then
disp "The given IPv4 is valid."
fi
return 0
fi
fi
if [[ -t 1 ]]; then
disp "The given parameter is NOT a valid IPv4."
# Start with a regex format test (four octets)
if [[ $ip =~ ^([0-9]{1,3}\.){3}[0-9]{1,3}$ ]]; then
local old_ifs=$IFS
IFS='.'
read -r -a ip_arr <<< "$ip"
IFS=$old_ifs
# Ensure each octet is between 0 and 255
local oct
for oct in "${ip_arr[@]}"; do
# Reject leading plus/minus or empty entries
if [[ -z $oct || $oct =~ [^0-9] ]]; then
[[ -t 1 ]] && disp "The given parameter is NOT a valid IPv4."
return 1
fi
if (( oct > 255 )); then
[[ -t 1 ]] && disp "The given parameter is NOT a valid IPv4."
return 1
fi
done
[[ -t 1 ]] && disp "The given IPv4 is valid."
return 0
fi
[[ -t 1 ]] && disp "The given parameter is NOT a valid IPv4."
return 1
}
export -f isipv4
# ------------------------------------------------------------------------------
# ------------------------------------------------------------------------------
# Determine if parameter is a valid IPv4 address
# ------------------------------------------------------------------------------
isipv6 ()
# Determine if parameter is a valid IPv6 address
# Usage: isipv6 <ip_address>
isipv6()
{
local ip="$1"
local regex='^([0-9a-fA-F]{0,4}:){1,7}[0-9a-fA-F]{0,4}$'
if [[ $ip =~ $regex ]]; then
if [[ -t 1 ]]; then
disp "The given IPv6 is valid."
fi
return 0
if [[ -t 1 ]]; then
disp "The given IPv6 is valid."
fi
return 0
fi
if [[ -t 1 ]]; then
disp "The given parameter is not a valid IPv6."
disp "The given parameter is not a valid IPv6."
fi
return 1
}
export -f isipv6
# ------------------------------------------------------------------------------
# ------------------------------------------------------------------------------
# Encode a string so it can be used as a URL parameter
# Usage: urlencode <string>
urlencode() {
local LANG=C
local str="$*"
local length="${#str}"
for (( i = 0; i < length; i++ )); do
local c="${str:i:1}"
case "$c" in
[a-zA-Z0-9.~_-]) printf '%s' "$c" ;;
' ') printf '+' ;;
*) printf '%%%02X' "'$c" #| cut -d' ' -f2 ;;
esac
done
}
export -f urlencode
# ------------------------------------------------------------------------------
# ------------------------------------------------------------------------------
# Fetch and display external IP information
# Usage: myextip [-i|--ip] [-s|--isp] [-l|--loc] [-c|--coord]
# If no option is provided, all information will be displayed.
# Options:
# -h, --help Display help screen
# -i, --ip Display only the external IP address
# -s, --isp Display only the ISP name
# -l, --loc Display only the location (city, region, country)
# -c, --coord Display only the coordinates (latitude, longitude)
# -a, --as Display only the Autonomous System (AS) information
# -R, --raw Display raw JSON response
myextip() {
local show_ip=false show_isp=false show_loc=false
local show_coord=false show_as=false show_raw=false
local all=true
# Parse arguments
while [[ "$#" -gt 0 ]]; do
case "$1" in
-i|--ip)
show_ip=true
all=false
;;
-s|--isp)
show_isp=true
all=false
;;
-l|--loc)
show_loc=true
all=false
;;
-c|--coord)
show_coord=true
all=false
;;
-a|--as)
show_as=true
all=false
;;
-R|--raw)
all=false
show_raw=true
;;
-h|--help)
printf "Fetch and display external IP information.\n\n"
printf "Usage: myextip [-i|--ip] [-s|--isp] [-l|--loc] [-c|--coord] [-a|--as] [-R|--raw]\n\n"
printf "Options:\n"
printf "\t-h, --help\tDisplay this help screen\n"
printf "\t-i, --ip\tDisplay only the external IP address\n"
printf "\t-s, --isp\tDisplay only the ISP name\n"
printf "\t-l, --loc\tDisplay only the location (city, region, country)\n"
printf "\t-c, --coord\tDisplay only the coordinates (latitude, longitude)\n"
printf "\t-a, --as\tDisplay only the Autonomous System (AS) information\n"
printf "\t-R, --raw\tDisplay raw JSON response\n"
return 0
;;
--)
shift
break
;;
*)
disp E "Unknown option: $1, use \"myextip --help\" to display usage."
return 1
;;
esac
shift
done
# Fetch data. Allow overriding endpoint via env var MYEXTIP_URL
local MYEXTIP_URL
MYEXTIP_URL=${MYEXTIP_URL:-http://ip-api.com/json/}
local response
if ! response=$(dwl "$MYEXTIP_URL"); then
disp E "Failed to fetch external IP information from $MYEXTIP_URL"
return 2
fi
# Parse with jq when available and when raw wasn't requested. The jq filter
# is tolerant to field-name differences between providers (ip-api / ipinfo).
if command -v jq >/dev/null 2>&1 && [[ "$show_raw" != true ]]; then
echo "$response" | jq -r --argjson all "$all" --argjson ip "$show_ip" \
--argjson isp "$show_isp" --argjson loc "$show_loc" \
--argjson coord "$show_coord" --argjson as "$show_as" '
[
(if $all or $ip then "IP Address : \(.query // .ip)" else empty end),
(if $all or $isp then "ISP : \(.isp // .org)" else empty end),
(if $all or $loc then
("Location : " + ((.city // "") + (if .city then ", " else "" end) + (if .regionName then .regionName else .region end) + (if .country then ", " + .country else "" end)))
else empty end),
(if $all or $coord then (if (.lat and .lon) then "Coordinates: \(.lat), \(.lon)" elif .loc then "Coordinates: \(.loc)" else empty end) else empty end),
(if $all or $as then "AS : \(.as // .org)" else empty end)
] | .[]'
else
[[ "$show_raw" != true ]] && disp W "jq is not installed, displaying raw JSON response."
echo "$response"
fi
}
export -f myextip
# ------------------------------------------------------------------------------
# ------------------------------------------------------------------------------
# EOF

View File

@@ -1,5 +1,6 @@
#!/usr/bin/env bash
# ------------------------------------------------------------------------------
# Copyright (c) 2013-2022 Geoffray Levasseur <fatalerrors@geoffray-levasseur.org>
# Copyright (c) 2013-2026 Geoffray Levasseur <fatalerrors@geoffray-levasseur.org>
# Protected by the BSD3 license. Please read bellow for details.
#
# * Redistribution and use in source and binary forms,
@@ -35,45 +36,64 @@
# ------------------------------------------------------------------------------
# Look for a package within installed one
# ------------------------------------------------------------------------------
pkgs ()
# Usage: dpkgs <string>
pkgs()
{
local count=0
for opt in $@ ; do
case $opt in
"-h"|"--help")
echo "dpkgs: look for an installed package by it's name."
echo
echo "Usage: dpkgs <string>"
local ignore_case=0
local PARSED
PARSED=$(getopt -o hi --long help,ignore-case -n 'pkgs' -- "$@")
if [[ $? -ne 0 ]]; then
disp E "Invalid options, use \"pkgs --help\" to display usage."
return 1
fi
eval set -- "$PARSED"
while true; do
case "$1" in
-h|--help)
printf "pkgs: Look for an installed package by its name.\n\n"
printf "Usage: pkgs [options] <string>\n\n"
printf "Options:\n"
printf "\t-h, --help\tDisplay this help screen\n"
printf "\t-i, --ignore-case\tIgnore case distinctions\n"
return 0
;;
"-"*)
disp E "Invalid option, use \"dpkgs --help\" to display usage."
echo
return 1
-i|--ignore-case)
ignore_case=1
shift
;;
--)
shift
break
;;
*)
local pkg=$1 && shift
count=$(( $count + 1 ))
[[ $count -gt 1 ]] &&
disp E "Please specify a package name, without space, eventually partial." &&
return 1
disp E "Invalid option: $1"
return 1
;;
esac
done
[[ $count -lt 1 ]] &&
disp E "Please specify a package name, without space, eventually partial." &&
local pkg="$1"
[[ -z "$pkg" ]] && {
disp E "Please specify a package name, without space, eventually partial."
return 1
}
# Build grep command
local grep_opt=""
(( ignore_case )) && grep_opt="-i"
command -v dpkg >/dev/null 2>&1 && local cmd="dpkg -l"
command -v rpm >/dev/null 2>&1 && local cmd="rpm -qa"
if [[ -z $cmd ]]; then
disp E "No usable package manager seems unavialable."
return 2
disp E "No usable package manager seems unavialable."
return 2
fi
$cmd | grep $pkg
$cmd | grep $grep_opt $pkg
}
export -f pkgs
# ------------------------------------------------------------------------------
# EOF

View File

@@ -1,5 +1,6 @@
#!/usr/bin/env bash
# ------------------------------------------------------------------------------
# Copyright (c) 2013-2022 Geoffray Levasseur <fatalerrors@geoffray-levasseur.org>
# Copyright (c) 2013-2026 Geoffray Levasseur <fatalerrors@geoffray-levasseur.org>
# Protected by the BSD3 license. Please read bellow for details.
#
# * Redistribution and use in source and binary forms,
@@ -35,19 +36,93 @@
# ------------------------------------------------------------------------------
# Search processes matching the given string
# ------------------------------------------------------------------------------
ppg ()
# Usage: ppg <string>
ppg()
{
ps -edf | grep $@ | grep -v "grep $@"
if [[ "$1" == "-h" || "$1" == "--help" ]]; then
printf "ppg: Search processes matching the given string.\n\n"
printf "Usage: ppg <string>\n\n"
printf "Options:\n"
printf "\t-h, --help\t\tDisplay this help screen\n"
return 0
fi
if [[ -z "$1" ]]; then
disp E "Usage: ppg <string>"
return 1
fi
ps -edf | grep "$@" | grep -v "grep $@"
}
export -f ppg
# ------------------------------------------------------------------------------
# ------------------------------------------------------------------------------
# List processes owned by a specific user
# Usage: ppu <username>
ppu()
{
if [[ "$1" == "-h" || "$1" == "--help" ]]; then
printf "ppu: List processes owned by a specific user.\n\n"
printf "Usage: ppu <username>\n\n"
printf "Options:\n"
printf "\t-h, --help\t\tDisplay this help screen\n"
return 0
fi
if [[ -z "$1" ]]; then
disp E "Usage: ppu <username>"
return 1
fi
# -u lists processes for a specific user
# -o provides a clean, standard output format
ps -u "$1" -o pid,user,%cpu,%mem,start,time,command
}
export -f ppu
# ------------------------------------------------------------------------------
# ------------------------------------------------------------------------------
# List processes by exact command name (no path/parameters)
# Usage: ppn <command_name>
ppn()
{
if [[ "$1" == "-h" || "$1" == "--help" ]]; then
printf "ppn: List processes by exact command name (no path/parameters).\n\n"
printf "Usage: ppn <command_name>\n\n"
printf "Options:\n"
printf "\t-h, --help\t\tDisplay this help screen\n"
return 0
fi
if [[ -z "$1" ]]; then
disp E "Usage: ppn <command_name>"
return 1
fi
# -e: select all processes
# -o: specify custom output columns (PID and Command name)
# grep -w: ensures exact word matching so 'bash' doesn't match 'dbash'
ps -eo pid,comm | grep -w "$1"
}
export -f ppn
# ------------------------------------------------------------------------------
# ------------------------------------------------------------------------------
# Get PID list of the given process name
# ------------------------------------------------------------------------------
gpid ()
# Usage: ppid <process_name [process_name2 ...]>
gpid()
{
if [[ "$1" == "-h" || "$1" == "--help" ]]; then
printf "gpid: Get PID list of the given process name.\n\n"
printf "Usage: gpid <process_name [process_name2 ...]>\n\n"
printf "Options:\n"
printf "\t-h, --help\t\tDisplay this help screen\n"
return 0
fi
if [[ -z "$1" ]]; then
disp E "Usage: gpid <process_name [process_name2 ...]>"
return 1
fi
[[ $UID -eq 0 ]] && local psopt="-A"
[[ $# -eq 1 ]] && local single=1
for pid in $@; do
@@ -61,15 +136,65 @@ gpid ()
[[ $result ]] || return 1
}
export -f gpid
# ------------------------------------------------------------------------------
# ------------------------------------------------------------------------------
# Kill all processes owned by the given users
# ------------------------------------------------------------------------------
ku ()
# Kill all processes owned by the given users (kill user)
# Usage: ku <username1 [username2 ...]>
ku()
{
if [[ "$1" == "-h" || "$1" == "--help" ]]; then
printf "ku: Kill all processes owned by the given users.\n\n"
printf "Usage: ku <username1 [username2 ...]>\n\n"
printf "Options:\n"
printf "\t-h, --help\t\tDisplay this help screen\n"
return 0
fi
if [[ -z "$1" ]]; then
disp E "Usage: ku <username1 [username2 ...]>"
return 1
fi
for u in $@; do
killall -u $u
killall -u "$u"
done
}
export -f ku
# ------------------------------------------------------------------------------
# ------------------------------------------------------------------------------
# Kill all children of a process then the process (kill tree)
# Usage: kt <pid> [kill_options]
kt()
{
if [[ "$1" == "-h" || "$1" == "--help" ]]; then
printf "kt: Kill all children of a process then the process (kill tree).\n\n"
printf "Usage: kt <pid> [kill_options]\n\n"
printf "Options:\n"
printf "\t-h, --help\t\tDisplay this help screen\n"
return 0
fi
if [[ -z "$1" ]]; then
disp E "Usage: ppg <string>"
return 1
fi
local parent_pid="$1"
shift
if [[ "$parent_pid" == "0" || "$parent_pid" == "1" ]]; then
disp E "Safety abort: Refusing to kill PID $parent_pid (system critical)."
return 1
fi
children_pids=$(pgrep -P "$parent_pid")
for pid in $children_pids; do
kt "$pid" "$@" || break
done
kill "$@" "$parent_pid"
}
# ------------------------------------------------------------------------------
# EOF

View File

@@ -1,5 +1,6 @@
#!/usr/bin/env bash
# ------------------------------------------------------------------------------
# Copyright (c) 2013-2022 Geoffray Levasseur <fatalerrors@geoffray-levasseur.org>
# Copyright (c) 2013-2026 Geoffray Levasseur <fatalerrors@geoffray-levasseur.org>
# Protected by the BSD3 license. Please read bellow for details.
#
# * Redistribution and use in source and binary forms,
@@ -35,17 +36,26 @@
# ------------------------------------------------------------------------------
# timer_* functions : internal timing function for prompt
# ------------------------------------------------------------------------------
# Usage: timer_now
# This function returns the current time in nanoseconds since the epoch. It
# first tries to use the %N format specifier for nanoseconds, but if that is
# not supported (e.g., on older systems), it falls back to seconds.
function timer_now
{
date +%s%N
date +%s%N 2>/dev/null || date +%s
}
# Usage: timer_start
# This function initializes the timer_start variable with the current time in
# nanoseconds. It is used to measure the elapsed time for the prompt.
function timer_start
{
timer_start=${timer_start:-$(timer_now)}
}
# Usage: timer_stop
# This function calculates the elapsed time since timer_start and formats it
# into a human-readable string with appropriate units (us, ms, s, m, h
function timer_stop
{
local delta_us=$((($(timer_now) - $timer_start) / 1000))
@@ -74,23 +84,26 @@ function timer_stop
}
# ------------------------------------------------------------------------------
# Function triguered internaly by bash : defining prompt
# ------------------------------------------------------------------------------
set_prompt ()
# Function triggered internally by bash : defining prompt
# Usage: set_prompt
# This function is called by bash before displaying the prompt. It sets the
# PS1 variable to a custom prompt that includes the exit status of the last
# command, the elapsed time of the last command, and the current user and host.
set_prompt()
{
Last_Command=$? # Must come first!
Blue='\[\e[0;34m\]'
White='\[\e[01;37m\]'
Yellow='\[\e[01;93m\]'
Red='\[\e[01;31m\]'
Green='\[\e[01;32m\]'
OnGrey='\[\e[47m\]'
OnRed='\[\e[41m\]'
OnBlue='\[\e[44m\]'
ICyan='\[\e[0;96m\]'
Default='\[\e[00m\]'
FancyX='\342\234\227'
Checkmark='\342\234\223'
local Last_Command=$? # Must come first!
local Blue='\[\e[0;34m\]'
local White='\[\e[01;37m\]'
local Yellow='\[\e[01;93m\]'
local Red='\[\e[01;31m\]'
local Green='\[\e[01;32m\]'
local OnGrey='\[\e[47m\]'
local OnRed='\[\e[41m\]'
local OnBlue='\[\e[44m\]'
local ICyan='\[\e[0;96m\]'
local Default='\[\e[00m\]'
local FancyX='\342\234\227'
local Checkmark='\342\234\223'
# Begin with time
PS1="\[\e[s$Blue$OnGrey [ \t ] $OnBlue"
@@ -123,3 +136,7 @@ set_prompt ()
# the text color to the default.
PS1+="$ICyan\\w \\\$$Default "
}
# ------------------------------------------------------------------------------
# EOF

View File

@@ -1,5 +1,6 @@
#!/usr/bin/env bash
# ------------------------------------------------------------------------------
# Copyright (c) 2013-2022 Geoffray Levasseur <fatalerrors@geoffray-levasseur.org>
# Copyright (c) 2013-2026 Geoffray Levasseur <fatalerrors@geoffray-levasseur.org>
# Protected by the BSD3 license. Please read bellow for details.
#
# * Redistribution and use in source and binary forms,
@@ -35,152 +36,168 @@
# ------------------------------------------------------------------------------
# genpwd : generate a password with different criteria
# default 16 car with up and low car, symbol and number
# Usage: genpwd [options] [--extracars=<cars>] [--length=<n>] [nb_passwd]
# Options:
# -h, --help Display that help screen
# -s, --nosymbols Exclude symbols
# -n, --nonumbers Exclude numbers
# -u, --noup Exclude uppercase letters
# -l, --nolow Exclude lowercase letters
# -e=<c>, --extracars=<c>
# Add the given caracters to the possible caracter list
# -L=<n>, --length=<n>
# Set length of the password (default is 16)
# -o=<n>, --occurences=<n>
# Set the maximum occurences of a same caracter (default is 2)
# The function is very slow on Windows
# ------------------------------------------------------------------------------
genpwd()
{
local length=16
local occurs=2 # Bug, if set to 1, seems to be ignored
local symb=1 maj=1 min=1 numb=1
local nbpwd=1
local extcar
for opt in $@; do
case $opt in
"-h"|"--help")
echo "genpwd: generate one or more secure random password."
echo
echo "Usage: genpwd [options] [--extracars=<cars>] [--length=<n>] [nb_passwd]"
echo
echo "Options:"
echo " -h, --help Display that help screen"
echo " -s, --nosymbols Exclude symbols"
echo " -n, --nonumbers Exclude numbers"
echo " -u, --noup Exclude uppercase letters"
echo " -l, --nolow Exclude lowercase letters"
echo " -e=<c>, --extracars=<c>"
echo " Add the given caracters to the possible caracter list"
echo " -L=<n>, --length=<n>"
echo " Set length of the password (default is $length)"
echo " -o=<n>, --occurences=<n>"
echo " Set the maximum occurences of a same caracter (default is $occurs)"
echo
echo "If the --extracars parameter is given, at least one of the given caracter will"
echo "be used in the final password."
echo
echo "Please note that some caracters might be interpreted by Bash or Awk programs,"
echo "and thus, cannot be used without provoquing errors. Those identified caracters"
echo "are :"
echo ' * ? \ $ { }'
echo
return 0
;;
"-s"|"--nosymbols")
symb=0
;;
"-n"|"--nonumbers")
numb=0
;;
"-u"|"--noup")
maj=0
;;
"-l"|"--nolow")
min=0
;;
"-e"?*|"--extracars"?*)
local extcar=$(echo "$opt" | cut -f 2- -d '=')
;;
"-L"?*|"--length"?*)
local length=$(echo "$opt" | cut -f 2- -d '=')
if ! [[ $length =~ ^[0-9]+$ ]]; then
disp E "The --length parameter requires a number."
return 1
fi
;;
"-o"?*|"--occurences"?*)
local occurs=$(echo "$opt" | cut -f 2- -d '=')
if ! [[ $occurs =~ ^[1-9]+$ ]]; then
disp E "The --occurs parameter requires a number from 1 to 9."
return 1
fi
;;
"-*")
disp E "Unknow parameter ${opt}."
return 1
;;
*)
if ! [[ $opt =~ ^[1-9]+$ ]]; then
disp E "Unknow parameter ${opt}."
return 1
else
local nbpwd=$opt
fi
;;
esac
local PARSED
PARSED=$(getopt -o hsnu l e:L:o: --long \
help,nosymbols,nonumbers,noup,nolow,extracars:,length:,occurences: -n 'genpwd' -- "$@")
if [[ $? -ne 0 ]]; then return 1; fi
eval set -- "$PARSED"
while true; do
case "$1" in
-h|--help)
printf "genpwd: Generate secure random password(s).\n\n"
printf "Usage: genpwd [options] [nb_passwd]\n\n"
printf "Options:\n"
printf "\t-h, --help\t\tDisplay this help screen\n"
printf "\t-s, --nosymbols\t\tExclude symbols\n"
printf "\t-n, --nonumbers\t\tExclude numbers\n"
printf "\t-u, --noup\t\tExclude uppercase letters\n"
printf "\t-l, --nolow\t\tExclude lowercase letters\n"
printf "\t-e, --extracars <c>\tAdd characters to list\n"
printf "\t-L, --length <n>\tSet password length (default: 16)\n"
printf "\t-o, --occurences <n>\tMax occurences per character (default: 2)\n"
return 0
;;
-s|--nosymbols)
symb=0
shift
;;
-n|--nonumbers)
numb=0
shift
;;
-u|--noup)
maj=0
shift
;;
-l|--nolow)
min=0
shift
;;
-e|--extracars)
extcar="$2"
shift 2
;;
-L|--length)
length="$2"
if ! [[ $length =~ ^[0-9]+$ ]]; then
disp E "The --length parameter requires a number."
return 1
fi
shift 2
;;
-o|--occurences)
occurs="$2"
if ! [[ $occurs =~ ^[1-9]+$ ]]; then
disp E "The --occurs parameter requires a number from 1 to 9."
return 1
fi
shift 2
;;
--)
shift; break
;;
*)
break
;;
esac
done
if [[ -n "$1" ]]; then
nbpwd="$1"
if ! [[ $nbpwd =~ ^[0-9]+$ ]]; then
disp E "The number of password to generate must be a number."
return 1
fi
fi
# Function selecting a random caracter from the list in parameter
pickcar()
{
# When a character is picked we check if it's not appearing already twice
# elsewhere, we choose an other char, to compensate weak bash randomizer
while [[ -z $char ]]; do
local char=$(echo ${1:RANDOM%${#1}:1} $RANDOM)
if [[ $(awk -F"$char" '{print NF-1}' <<< "$picked") -gt $occurs ]]; then
unset char
fi
done
picked+="$char"
echo "$char"
pickcar() {
# When a character is picked we check if it's not appearing already twice
# elsewhere, we choose an other char, to compensate weak bash randomizer
while [[ -z $char ]]; do
local char="${1:RANDOM%${#1}:1} $RANDOM"
if [[ $(awk -F"$char" '{print NF-1}' <<<"$picked") -gt $occurs ]]; then
unset char
fi
done
picked+="$char"
echo "$char"
}
disp I "Generating $nbpwd passwords, please wait..."
for n in $( seq 1 $nbpwd ); do
{
local carset='' # store final caracter set to use
local picked='' # store already used caracter
local rlength=0 # store already assigned length of caracters
for (( n=1; n<=nbpwd; n++ )); do
{
local carset='' # store final caracter set to use
local picked='' # store already used caracter
local rlength=0 # store already assigned length of caracters
# ?, *, $ and \ impossible to use to my knowledge as it would be interpreted
if [[ $symb == 1 ]]; then
pickcar '!.@#&%/^-_'
carset+='!.@#&%/^-_'
(( rlength++ ))
fi
if [[ $numb == 1 ]]; then
pickcar '0123456789'
carset+='0123456789'
(( rlength++ ))
fi
if [[ $maj == 1 ]]; then
pickcar 'ABCDEFGHIJKLMNOPQRSTUVWXYZ'
carset+='ABCDEFGHIJKLMNOPQRSTUVWXYZ'
(( rlength++ ))
fi
if [[ $min == 1 ]]; then
pickcar 'abcdefghijklmnopqrstuvwxyz'
carset+='abcdefghijklmnopqrstuvwxyz'
(( rlength++ ))
fi
if [[ -n $extcar ]]; then
pickcar "$extcar"
carset+=$extcar
(( rlength++ ))
fi
# ?, *, $ and \ impossible to use to my knowledge as it would be interpreted
if [[ $symb == 1 ]]; then
pickcar '!.@#&%/^-_'
carset+='!.@#&%/^-_'
((rlength++))
fi
if [[ $numb == 1 ]]; then
pickcar '0123456789'
carset+='0123456789'
((rlength++))
fi
if [[ $maj == 1 ]]; then
pickcar 'ABCDEFGHIJKLMNOPQRSTUVWXYZ'
carset+='ABCDEFGHIJKLMNOPQRSTUVWXYZ'
((rlength++))
fi
if [[ $min == 1 ]]; then
pickcar 'abcdefghijklmnopqrstuvwxyz'
carset+='abcdefghijklmnopqrstuvwxyz'
((rlength++))
fi
if [[ -n $extcar ]]; then
pickcar "$extcar"
carset+=$extcar
((rlength++))
fi
# Check if we have enough car to have something viable
if [[ ${#carset} -lt $length ]]; then
disp E 'Not enought caracters are authorised for the password length.'
disp E 'Please allow more caracter (preferably) or reduce password lentgh.'
return 1
fi
# Check if we have enough car to have something viable
if [[ ${#carset} -lt $length ]]; then
disp E 'Not enought caracters are authorised for the password length.'
disp E 'Please allow more caracter (preferably) or reduce password lentgh.'
return 1
fi
for i in $( seq 1 $(( $length - $rlength )) ); do
pickcar "$carset"
done
} | sort -R | awk '{printf "%s", $1}'
unset picked carset rlength
echo
for i in $(seq 1 $(($length - $rlength))); do
pickcar "$carset"
done
} | sort -R | awk '{printf "%s", $1}'
unset picked carset rlength
echo
done
}
export -f genpwd
# ------------------------------------------------------------------------------
# EOF

View File

@@ -1,5 +1,6 @@
#!/usr/bin/env bash
# ------------------------------------------------------------------------------
# Copyright (c) 2013-2022 Geoffray Levasseur <fatalerrors@geoffray-levasseur.org>
# Copyright (c) 2013-2026 Geoffray Levasseur <fatalerrors@geoffray-levasseur.org>
# Protected by the BSD3 license. Please read bellow for details.
#
# * Redistribution and use in source and binary forms,
@@ -35,37 +36,110 @@
# ------------------------------------------------------------------------------
# Let the rain fall
# ------------------------------------------------------------------------------
# Usage: rain [OPTIONS]
# Options:
# -s, --speed NUM Set the drop delay in seconds (default: 0.050).
# Lower values = faster rain.
# -c, --color COLOR Set the color theme (default: white).
# -h, --help Display this help message and exit.
# Available Colors:
# green : The classic Matrix digital rain
# blue : Deep ocean blue gradients
# red : Crimson/Blood rain
# yellow : Amber and gold tones
# cyan : Electric cyan/turquoise
# white : Greyscale and white (original style)
rain()
{
show_usage() {
printf "Usage: rain [OPTIONS]\n"
printf "Options:\n"
printf "\t-s, --speed NUM Set the drop delay in seconds (default: 0.050).\n"
printf "\t Lower values = faster rain.\n"
printf "\t-c, --color COLOR Set the color theme (default: white).\n"
printf "\t-h, --help Display this help message and exit.\n\n"
printf "Available Colors:\n"
printf "\t\e[32mgreen\e[0m\t: The classic Matrix digital rain\n"
printf "\t\e[34mblue\e[0m\t: Deep ocean blue gradients\n"
printf "\t\e[31mred\e[0m\t: Crimson/Blood rain\n"
printf "\t\e[33myellow\e[0m\t: Amber and gold tones\n"
printf "\t\e[36mcyan\e[0m\t: Electric cyan/turquoise\n"
printf "\twhite\t: Greyscale and white (original style)\n\n"
printf "Example: rain --color green --speed 0.03\n"
}
local step_duration=0.050
local base_color="white" # default color scheme, can be overridden by --color
# Analyse arguments
while [[ "$#" -gt 0 ]]; do
case $1 in
-s|--speed)
if [[ -n "$2" && ! "$2" =~ ^- ]]; then
step_duration="$2"; shift
else
disp E "--speed requires a numeric value."
show_usage && return 1
fi
;;
-c|--color)
if [[ -n "$2" && ! "$2" =~ ^- ]]; then
base_color="$2"; shift
else
disp E "--color requires a color name."
show_usage && return 1
fi
;;
-h|--help)
show_usage && return 0
;;
*)
disp E "Unknown option: $1"
show_usage && return 1
;;
esac
shift
done
# Define colors (256-colors gradients)
local rain_colors=()
case $base_color in
green) # Matrix style green
for i in {22..28} {34..40} {46..48}; do rain_colors+=("\e[38;5;${i}m"); done ;;
blue) # Deep ocean blues
for i in {17..21} {27..33} {39..45}; do rain_colors+=("\e[38;5;${i}m"); done ;;
red) # Crimson / blood red
for i in {52..52} {88..88} {124..124} {160..160} {196..201}; do rain_colors+=("\e[38;5;${i}m"); done ;;
yellow) # Amber / gold
for i in {58..58} {100..100} {142..142} {184..184} {226..229}; do rain_colors+=("\e[38;5;${i}m"); done ;;
cyan) # Electric cyan / turquoise
for i in {30..31} {37..38} {44..45} {50..51}; do rain_colors+=("\e[38;5;${i}m"); done ;;
*) # Greyscale / white (original style)
rain_colors=("\e[37m" "\e[37;1m")
for i in {244..255}; do rain_colors+=("\e[38;5;${i}m"); done ;;
esac
local exit_st=0
local rain_cars=("|" "│" "┃" "┆" "┇" "┊" "┋" "╽" "╿")
local rain_colors=("\e[37m" "\e[37;1m")
# More from 256 color mode
for i in {244..255}; do
rain_colors=( "${rain_colors[@]}" "\e[38;5;${i}m" )
done
local rain_tab=${#rain_cars[@]}
local rain_color_tab=${#rain_colors[@]}
local num_rain_metadata=5
local term_height=$(tput lines)
local term_width=$(tput cols)
local step_duration=0.050
local X=0 Y=0 drop_length=0 rain_drop=0
local max_rain_width=0 new_rain_odd=0 falling_odd=0
sigwinch() {
term_width=$(tput cols)
term_height=$(tput lines)
#step_duration=0.025
(( max_rain_width = term_width * term_height / 4 ))
(( max_rain_height = term_height < 10 ? 1 : term_height / 10 ))
((max_rain_width = term_width * term_height / 4))
((max_rain_height = term_height < 10 ? 1 : term_height / 10))
# In percentage
(( new_rain_odd = term_height > 50 ? 100 : term_height * 2 ))
(( new_rain_odd = new_rain_odd * 75 / 100 ))
(( falling_odd = term_height > 25 ? 100 : term_height * 4 ))
(( falling_odd = falling_odd * 90 / 100 ))
((new_rain_odd = term_height > 50 ? 100 : term_height * 2))
((new_rain_odd = new_rain_odd * 75 / 100))
((falling_odd = term_height > 25 ? 100 : term_height * 4))
((falling_odd = falling_odd * 90 / 100))
}
do_exit() {
@@ -80,19 +154,19 @@ rain()
Y=${rains[idx + 1]}
drop_length=${rains[idx + 4]}
for ((y = Y; y < Y + drop_length; y++)); do
(( y < 1 || y > term_height )) && continue
((y < 1 || y > term_height)) && continue
echo -ne "\e[${y};${X}H "
done
done
for ((idx = 0; idx < num_rains * num_rain_metadata; idx += num_rain_metadata)); do
if (( 100 * RANDOM / 32768 < falling_odd )); then
if ((100 * RANDOM / 32768 < falling_odd)); then
# Falling
if (( ++rains[idx + 1] > term_height )); then
if ((++rains[idx + 1] > term_height)); then
# Out of screen, bye sweet <3
rains=("${rains[@]:0:idx}"
"${rains[@]:idx+num_rain_metadata:num_rains*num_rain_metadata}")
(( num_rains-- ))
((num_rains--))
continue
fi
fi
@@ -102,8 +176,8 @@ rain()
drop_color=${rains[idx + 3]}
drop_length=${rains[idx + 4]}
for ((y = Y; y < Y + drop_length; y++)); do
(( y < 1 || y > term_height )) && continue
echo -ne "\e[${y};${X}H${drop_color}${rain_drop}"
((y < 1 || y > term_height)) && continue
printf "\e[${y};${X}H${drop_color}${rain_drop}"
done
done
}
@@ -112,30 +186,30 @@ rain()
trap sigwinch WINCH
# No echo stdin and hide the cursor
stty -echo
echo -ne "\e[?25l"
printf "\e[?25l"
printf "\e[2J"
echo -ne "\e[2J"
local rains=()
local num_rains=0
sigwinch
while (( exit_st <= 0 )); do
if (( $exit_st <=0 )); then
while ((exit_st <= 0)); do
if (($exit_st <= 0)); then
read -n 1 -t $step_duration ch
case "$ch" in
q|Q)
do_exit
q | Q)
do_exit
;;
esac
if (( num_rains < max_rain_width )) && (( 100 * RANDOM / 32768 < new_rain_odd )); then
if ((num_rains < max_rain_width)) && ((100 * RANDOM / 32768 < new_rain_odd)); then
# Need new |, 1-based
rain_drop="${rain_cars[rain_tab * RANDOM / 32768]}"
drop_color="${rain_colors[rain_color_tab * RANDOM / 32768]}"
drop_length=$(( max_rain_height * RANDOM / 32768 + 1 ))
X=$(( term_width * RANDOM / 32768 + 1 ))
Y=$(( 1 - drop_length ))
rains=( "${rains[@]}" "$X" "$Y" "$rain_drop" "$drop_color" "$drop_length" )
(( num_rains++ ))
drop_length=$((max_rain_height * RANDOM / 32768 + 1))
X=$((term_width * RANDOM / 32768 + 1))
Y=$((1 - drop_length))
rains=("${rains[@]}" "$X" "$Y" "$rain_drop" "$drop_color" "$drop_length")
((num_rains++))
fi
# Let rain fall!
@@ -152,3 +226,6 @@ rain()
trap - WINCH
}
export -f rain
# ------------------------------------------------------------------------------
# EOF

View File

@@ -1,5 +1,6 @@
#!/usr/bin/env bash
# ------------------------------------------------------------------------------
# Copyright (c) 2013-2022 Geoffray Levasseur <fatalerrors@geoffray-levasseur.org>
# Copyright (c) 2013-2026 Geoffray Levasseur <fatalerrors@geoffray-levasseur.org>
# Protected by the BSD3 license. Please read bellow for details.
#
# * Redistribution and use in source and binary forms,
@@ -35,71 +36,124 @@
# ------------------------------------------------------------------------------
# Remove host from know_host (name and IP) for the active user
# ------------------------------------------------------------------------------
rmhost ()
# Usage: rmhost <hostname|ip> [hostname2|ip2 [...]]
rmhost()
{
if [[ "$#" -lt 1 ]]; then
disp E "Incorrect number of parameters."
disp E "Usage: rmhost <hostname|ip> [hostname2|ip2 [...]]"
return 1
fi
local PARSED
PARSED=$(getopt -o h --long help -n 'rmhost' -- "$@")
if [[ $? -ne 0 ]]; then return 1; fi
eval set -- "$PARSED"
while [[ $1 ]]; do
local hst=$1 && shift
isipv4 $hst > /dev/null
local v4=$?
isipv6 $hst > /dev/null
local v6=$?
if [[ $v4 -eq 0 || $v6 -eq 0 ]]; then
local ip=$hst
unset hst
fi
unset v4 v6
if [[ ! $ip && $hst ]]; then
ip=$(host $hst | grep "has address" | awk '{print $NF}')
[[ ! $? ]] &&
disp E "Impossible to extract IP from hostname." &&
return 1
fi
if [[ $hst ]]; then
disp I "Removing host $hst from ssh known_host..."
ssh-keygen -R $hst > /dev/null
fi
if [[ $ip ]]; then
disp I "Removing IP $ip from ssh known_host..."
ssh-keygen -R $ip > /dev/null
fi
unset hst ip
done
}
export -f rmhost
# ------------------------------------------------------------------------------
# Login root via SSH on the given machine
# ------------------------------------------------------------------------------
ssr ()
{
for opt in $@ ; do
case $opt in
"-h"|"--help")
echo "ssr: do a root user ssh login."
echo
echo "Usage: ssr <server [ssh options]>"
while true; do
case "$1" in
-h|--help)
printf "rmhost: Remove host/IP from ~/.ssh/known_hosts.\n\n"
printf "Usage: rmhost <hostname|ip> [hostname2|ip2 ...]\n\n"
printf "Options:\n"
printf " -h, --help Display this help screen\n"
return 0
;;
--)
shift
break
;;
*)
disp E "Invalid options, use \"rmhost --help\" to display usage."
break
;;
esac
done
[[ ! $1 ]] &&
disp E "Please specify the server you want to log in." &&
# Validation: Ensure at least one argument remains
if [[ $# -eq 0 ]]; then
disp E "Missing argument. Use 'rmhost --help' for usage."
return 1
fi
for target in "$@"; do
local hst=$target
isipv4 "$hst" >/dev/null
local v4=$?
isipv6 "$hst" >/dev/null
local v6=$?
if [[ $v4 -eq 0 || $v6 -eq 0 ]]; then
local ip=$hst
unset hst
fi
unset v4 v6
if [[ ! $ip && $hst ]]; then
if ! ip=$(host "$hst" 2>/dev/null | awk '/has address/ {print $NF; exit}'); then
disp E "Impossible to extract IP from hostname." &&
return 1
fi
[[ -z $ip ]] && {
disp E "Impossible to extract IP from hostname."
return 1;
}
fi
if [[ $hst ]]; then
disp I "Removing host $hst from ssh known_host..."
ssh-keygen -R $hst >/dev/null
fi
if [[ $ip ]]; then
disp I "Removing IP $ip from ssh known_host..."
ssh-keygen -R $ip >/dev/null
fi
unset hst ip
done
}
export -f rmhost
# ------------------------------------------------------------------------------
# ------------------------------------------------------------------------------
# Login root via SSH on the given machine
# Usage: ssr <server [ssh options]>
ssr()
{
local PARSED
PARSED=$(getopt -o h --long help -n 'ssr' -- "$@")
if [[ $? -ne 0 ]]; then return 1; fi
eval set -- "$PARSED"
while true; do
case "$1" in
-h|--help)
printf "ssr: SSH into a server as root.\n\n"
printf "Usage: ssr <server> [ssh_options...]\n\n"
printf "Options:\n"
printf "\t-h, --help\t\tDisplay this help screen\n"
return 0
;;
--)
shift
break
;;
*)
disp E "Invalid options, use \"ssr --help\" to display usage."
return 1
;;
esac
done
command -v ssh >/dev/null 2>&1 || {
disp E "ssh is not installed."
return 127
}
[[ ! $1 ]] && {
disp E "Please specify the server you want to log in."
return 1
}
local srv=$1 && shift
ssh -Y root@$srv $@
ssh -Y root@"$srv" "$@"
}
export -f ssr
# ------------------------------------------------------------------------------
# EOF

View File

@@ -1,5 +1,6 @@
#!/usr/bin/env bash
# ------------------------------------------------------------------------------
# Copyright (c) 2013-2022 Geoffray Levasseur <fatalerrors@geoffray-levasseur.org>
# Copyright (c) 2013-2026 Geoffray Levasseur <fatalerrors@geoffray-levasseur.org>
# Protected by the BSD3 license. Please read bellow for details.
#
# * Redistribution and use in source and binary forms,
@@ -33,24 +34,155 @@
# * OF SUCH DAMAGE.
# ------------------------------------------------------------------------------
export BASE_URL="https://git.geoffray-levasseur.org/fatalerrors/profile"
export UPDT_URL="$BASE_URL/raw/branch/master"
export ARCH_URL="$BASE_URL/archive/master.tar.gz"
# ------------------------------------------------------------------------------
# Check for profile updates
# ------------------------------------------------------------------------------
# Usage: check_updates [-q]
# If -q is specified, the function will operate in quiet mode (internal use only)
check_updates()
{
disp I "Checking for updates..."
local quiet=0
local PARSED=$(getopt -o hq --long help,quiet -n 'check_updates' -- "$@")
if [[ $? -ne 0 ]]; then
disp E "Invalid options, use \"check_updates --help\" to display usage."
return 1
fi
eval set -- "$PARSED"
while true; do
case "$1" in
-h|--help)
printf "check_updates: Check for new versions.\n\n"
printf "Usage: check_updates\n"
return 0
;;
-q|--quiet)
quiet=1
shift
;;
--)
shift
break
;;
*)
break
;;
esac
done
(( $quiet != 1 )) && disp I "Checking for updates..."
local vfile="/tmp/version"
wget "$UPDT_URL/version" -O $vfile 2&>1 /dev/null || {
disp E "Can\'t download information file, impossible to proceed!"
return 1
wget "$UPDT_URL/version" -O $vfile >/dev/null 2>&1 || {
disp E "Can't download version file, impossible to proceed!"
return 5
}
if [[ -s /tmp/version ]]; then
local lastver=$(cat /tmp/version)
if [[ $lastver != $PROFVERSION ]]; then
disp I "You have version $PROFVERSION installed. Version $lastver is available."
disp I "You should upgrade to last version when possible."
fi
if [[ -s $vfile ]]; then
local lastver=$(cat $vfile)
if [[ $lastver != $PROFVERSION ]]; then
disp I "You have version $PROFVERSION installed. Version $lastver is available."
(( $quiet != 1 )) && disp I "You should upgrade to last version when possible."
result=1
else
(( $quiet != 1 )) && disp I "Your version is up-to-date."
result=0
fi
rm -f $vfile
else
disp E "Impossible to read temporary file, impossible to proceed."
disp E "Impossible to read temporary file, impossible to proceed."
fi
unset lastver vfile
return $result
}
# ------------------------------------------------------------------------------
# ------------------------------------------------------------------------------
# Apply update to profile
# Usage: profile_upgrade
profile_upgrade()
{
local PARSED=$(getopt -o h --long help -n 'profile_upgrade' -- "$@")
if [[ $? -ne 0 ]]; then
printf "Invalid options, use \"profile_upgrade --help\" to display usage."
return 1
fi
eval set -- "$PARSED"
while true; do
case "$1" in
-h|--help)
printf "profile_upgrade: Upgrade the profile to the latest version.\n\n"
printf "Usage: profile_upgrade\n"
return 0
;;
--)
shift
break
;;
*)
disp E "Invalid options, use \"profile_upgrade --help\" to display usage."
return 1
;;
esac
done
if check_updates -q; then
disp "No update available."
return 0
fi
if [[ -s $MYPATH/profile.sh ]]; then
disp E "Installation path detection failed, cannot upgrade automatically."
return 1
fi
if [[ -d $MYPATH/.git ]]; then
disp I "Git installation detected, applying git pull."
local curdir=$(pwd)
cd $MYPATH
git pull || {
disp E "Git pull failed, upgrade not applyed."
cd "$curdir"
return 2
}
disp I "Successfully upgraded using git."
cd "$curdir"
else
disp I "No Git detected. Downloading and applying upgrade from archive..."
local tmpdir="/tmp/profile_upg.$$"
mkdir -p "$tmpdir" || {
disp E "Failed to create temporary directory."
return 4
}
local archive="$tmpdir/profile.tar.gz"
wget -q "$ARCH_URL" -O "$archive" || {
disp E "Failed to download archive."
rm -rf "$tmpdir"
return 5
}
tar -xzf "$archive" -C "$tmpdir" || {
disp E "Archive extraction failed."
rm -rf "$tmpdir"
return 6
}
disp I "Installing new version..."
cp -r "$tmpdir"/profile/* "$MYPATH"/ || {
disp E "Failed to copy new files to $MYPATH."
rm -rf "$tmpdir"
return 7
}
disp I "Upgrade complete. You should now logout and login again."
rm -rf "$tmpdir"
fi
}
# ------------------------------------------------------------------------------
# EOF

View File

@@ -1,7 +1,7 @@
#!/bin/bash
#!/usr/bin/env bash
# Begin profile
# ------------------------------------------------------------------------------
# Copyright (c) 2013-2022 Geoffray Levasseur <fatalerrors@geoffray-levasseur.org>
# Copyright (c) 2013-2026 Geoffray Levasseur <fatalerrors@geoffray-levasseur.org>
# Protected by the BSD3 license. Please read bellow for details.
#
# * Redistribution and use in source and binary forms,
@@ -35,42 +35,151 @@
# * OF SUCH DAMAGE.
# ------------------------------------------------------------------------------
if [[ ! $(echo $SHELL | grep bash) ]]; then
echo "That environmet script is designed to be used with bash or zsh being the shell."
echo "Please consider using bash or zsh instead, or patch me ;)!"
if [[ ! $SHELL =~ bash ]]; then
echo "That environment script is designed to be used with bash being the shell."
echo "Please consider using bash to enjoy our features!"
return 1
fi
# Required for associative arrays (4.0+) and namerefs (4.3+)
if ((BASH_VERSINFO[0] < 4)) || [[ ${BASH_VERSINFO[0]} -eq 4 && ${BASH_VERSINFO[1]} -lt 3 ]]; then
echo "[ Error ] This profile requires Bash 4.3 or higher."
echo "Current version: $BASH_VERSION"
return 1 2>/dev/null || exit 1
fi
# ------------------------------------------------------------------------------
# path* : private functions for PATH variable management
# ------------------------------------------------------------------------------
pathremove ()
pathremove()
{
local ifs=':'
local IFS=':'
local newpath
local dir
local pathvar=${2:-PATH}
for dir in ${!pathvar} ; do
if [ "$dir" != "$1" ] ; then
for dir in ${!pathvar}; do
if [ "$dir" != "$1" ]; then
newpath=${newpath:+$newpath:}$dir
fi
done
export $pathvar="$newpath"
}
pathprepend ()
pathprepend()
{
pathremove $1 $2
local pathvar=${2:-PATH}
export $pathvar="$1${!pathvar:+:${!pathvar}}"
}
pathappend ()
pathappend()
{
pathremove $1 $2
local pathvar=${2:-PATH}
export $pathvar="${!pathvar:+${!pathvar}:}$1"
}
# ------------------------------------------------------------------------------
# ------------------------------------------------------------------------------
# Configuration file parser
parse_conf()
{
local config_file="$1"
local current_section=""
local line key value
[[ ! -f "$config_file" ]] && return 1
while IFS='=' read -r key value || [[ -n "$key" ]]; do
# Internal trimming (removes leading/trailing whitespace & CR)
key="${key%"${key##*[![:space:]]}"}"
key="${key#"${key%%[![:space:]]*}"}"
key="${key%$'\r'}" # Strip potential Windows line endings
# Skip comments and empty lines
[[ -z "$key" || "$key" =~ ^[#\;] ]] && continue
# Section Detection: [section_name]
if [[ "$key" =~ ^\[([a-zA-Z0-9_]+)\]$ ]]; then
current_section="${BASH_REMATCH[1]}"
declare -g -A "CONF_$current_section"
continue
fi
# Secure Assignment (if inside a section)
if [[ -n "$current_section" ]]; then
# Clean the value
value="${value%"${value##*[![:space:]]}"}"
value="${value#"${value%%[![:space:]]*}"}"
value="${value%$'\r'}"
# Protect against command injection by disallowing certain characters in keys
value="${value//\`/}"
value="${value//\$\(/}"
# Correctly interpretet internal variables (e.g. $HOME)
if [[ "$value" == *\$* ]]; then
value=$(envsubst <<< "$value")
fi
# Strip quotes (handling both " and ')
value="${value%\"}"; value="${value#\"}"
value="${value%\'}"; value="${value#\'}"
# Use a nameref for safe, eval-free assignment
local -n current_array="CONF_$current_section"
current_array["$key"]="$value"
fi
done < "$config_file"
}
# ------------------------------------------------------------------------------
# ------------------------------------------------------------------------------
# Load command aliases from configuration
load_alias()
{
local section_name="CONF_$1"
# Check if the associative array exists using declare -p
[[ "$(declare -p "$section_name" 2>/dev/null)" != "declare -A"* ]] && return 1
# Create a nameref to the section array
local -n current_aliases="$section_name"
# Iterate safely over the keys of the associative array
for key in "${!current_aliases[@]}"; do
local cmd="${current_aliases[$key]}"
# Extract the base command (first word) safely without awk
local base_cmd="${cmd%% *}"
# Only alias if the base command is executable
if command -v "$base_cmd" >/dev/null 2>&1; then
alias "$key"="$cmd"
fi
done
}
# ------------------------------------------------------------------------------
# ------------------------------------------------------------------------------
# Load configuration values as environment variables
load_conf()
{
local section_name="CONF_$1"
[[ "$(declare -p "$section_name" 2>/dev/null)" != "declare -A"* ]] && return 1
local -n current_vars="$section_name"
for key in "${!current_vars[@]}"; do
# Export the key/value pair as a standard shell variable
# We use 'export' directly; Bash handles the assignment safely here
export "$key"="${current_vars[$key]}"
done
}
# ------------------------------------------------------------------------------
# ------------------------------------------------------------------------------
@@ -80,59 +189,42 @@ pathappend ()
# ------------------------------------------------------------------------------
# Store script's path (realpath -s resolve symlinks if profile.sh is a symlink)
export MYPATH=$(dirname $(realpath -s $0))
if [[ ! -e $MYPATH/profile.sh ]]; then
echo "[ Warning ] Path detection failed, using pwd..."
# Because we're more likely to be sourced, we use BASH_SOURCE to get the path
# of the sourced file instead of $0
if [[ -z "$PROFILE_PATH" ]]; then
export MYPATH=$(dirname "$(realpath -s "${BASH_SOURCE[0]}")")
else
export MYPATH="$PROFILE_PATH"
fi
if [[ ! -e "$MYPATH/profile.sh" ]]; then
echo "[ Warning ] Path detection failed, trying to use pwd..."
MYPATH=$(pwd)
if [[ ! -e $MYPATH/profile.sh ]]; then
echo "[ Error ] Impossible to determine installation path, pretty much nothing will work."
if [[ ! -e "$MYPATH/profile.sh" ]]; then
echo "[ Error ] Impossible to determine installation path, pretty much nothing will work."
fi
fi
if [[ ! -s $MYPATH/version ]]; then
if [[ ! -s "$MYPATH/version" ]]; then
echo "[ Warning ] Impossible to determine running version of profile, your installation might be broken."
fi
export PROFVERSION=$(cat $MYPATH/version)
export PROFVERSION=$(cat "$MYPATH"/version)
# Build PATH environment variable
if [[ $EUID -eq 0 ]] ; then
if [[ $EUID -eq 0 ]]; then
pathappend /sbin:/usr/sbin
fi
[[ -d /share/services/gestparc ]] && pathappend /share/services/gestparc
[[ -d ~/bin ]] && pathappend ~/bin
[[ -d ~/.local/bin ]] && pathappend ~/.local/bin
# Set bash history
export HISTSIZE=50000
export HISTIGNORE="&:[bf]g:exit"
# Set default pager
export PAGER=less
# More colors
export TERM=xterm-256color
# Set some compiling values
export CFLAGS="-O2 -pipe -march=native"
export MAKEFLAGS='-j12'
export PKGSOURCES='/share/src/archives'
# Default city for weather forcast
export DEFAULT_CITY="Toulouse"
# ------------------------------------------------------------------------------
# Default values could be altered after this line
# ------------------------------------------------------------------------------
# Load global configuration
[[ -f $MYPATH/etc/profile.conf ]] && . ~/.profile.conf
# Load personal configuration
[[ -f ~/.profile.conf ]] && . ~/.profile.conf
# Parse and load general configuration
export PROFILE_CONF="$MYPATH/profile.conf"
parse_conf "$PROFILE_CONF"
load_conf system # Load Bash system behavior configuration (history, pager, etc.)
load_conf general # General purpose configuration (compilation flags, etc.)
# Load module scripts
for script in $MYPATH/profile.d/*.sh ; do
if [ -r $script ] ; then
for script in $MYPATH/profile.d/*.sh; do
if [[ -r $script ]]; then
. $script
fi
done
@@ -140,34 +232,12 @@ done
# Interactive shell detection, two methods available each one of those might have different result
# depending on distribution
#shopt -q login_shell && INTERACTIVE=1
[[ $- == *i* ]] && INTERACTIVE=1
[[ $- == *i* ]] && export INTERACTIVE=1
if [[ $INTERACTIVE ]]; then
# For compiling (as we often compile with LFS/0linux...)
#Aliases
alias ll='ls -laFh --color=auto'
alias la='ls -Ah --color=auto'
alias l='ls -CF --color=auto'
alias ls='ls --color=auto'
alias grep='grep --color=auto'
alias egrep='egrep --color=auto'
alias fgrep='fgrep --color=auto'
alias qfind="find . -name "
alias mkck='make check'
alias mkin='make install'
alias mkdin='make DESTDIR=$PWD/dest-install install'
alias ssh='ssh -Y'
alias wget='wget -c' # resume mode by default
alias myip='curl ip.appspot.com'
# Human readable by default
alias df='df -H'
alias du='du -ch'
alias sdu='du -sk ./* | sort -n'
load_alias aliases
# Define PS1
trap 'timer_start' DEBUG
@@ -175,7 +245,8 @@ if [[ $INTERACTIVE ]]; then
# Set default language
setfr
showinfo
showinfo && printf "\n"
check_updates -q
disp I "Profile version $PROFVERSION chargé..."
fi

View File

@@ -1 +1 @@
3.3.1
3.95.2-4_beta_2