diff --git a/calm b/calm new file mode 100755 index 0000000..57f34e0 --- /dev/null +++ b/calm @@ -0,0 +1,37 @@ +#!/bin/bash +#LACKSETUP +# Calm a process down +# NEEDS_WORK: cleanup +# calm == only one process +# calm == all processes that match query +# calm * == if used in proc or a folder with just PID files, if not you will get an error +# calm .... OK +# set's NICE value to 0 +# need sudo +PIDS=$@ +errorFn() +{ + echo calm: Invalid operation or no such PID/process \(\"$(echo "$PIDS" | tr '\n' ' ' | cut -c -20)...\"\) + exit +} + +for pid in $PIDS +do + # Process to PID in elegant way + NEWPIDS=$(pidof "$pid") + if [ "$NEWPIDS" ] + then + BINNY=$pid + pid=$NEWPIDS + else + NEWBINS=$pid + BINNY=$(ps -p "$pid" -o comm= 2>/dev/null ) + if [ $? != 0 ] + then + errorFn + fi + fi + + echo Calming down $pid \("$BINNY"\)... + sudo renice -n 0 -p $pid; +done diff --git a/cdz b/cdz new file mode 100755 index 0000000..170076c --- /dev/null +++ b/cdz @@ -0,0 +1,83 @@ +#!/bin/bash + +if [[ $DAISY_INTERNAL -ne 1 ]]; +then + DAISY_INTERNAL=1 source $DAISY_SOURCE_FILE +fi + +target=$1 + +# Check if file exists +if [[ -z "$target" ]]; +then + echo "No target specified." + exit 1 +fi + +if ! test -f "$target"; +then + echo "File not found: \"$target\"" + exit 2 +fi + +file "$target" 1>/dev/null +exitcode=$? +report=$(file "$target") + +# Check for archive type, supported types are zip/tar/rar +comm1=(:) +comm2=(echo "Unsupported archive type$add: \"$target\"") +comm3=(:) + +echo $report | grep "tar archive" 1>/dev/null +istar=$? +echo $report | grep "Zip archive" 1>/dev/null +iszip=$? +echo $report | grep "RAR archive" 1>/dev/null +israr=$? + +# TAR archives come in many forms, if none of our tests say it's tar +# ...but it looks like tar and barks like tar, let's take the shot. +# Seems to work fairly well for the record. +RES=$(echo "$target" | grep ".tar") +if [[ RES != "" ]]; +then + istar=0 +fi + +# Now we set the right command +if (( istar == 0 )); then + comm2=(tar xvf "$target" -C) +elif (( iszip == 0 )); then + which unzip 1>/dev/null + exitcode=$? + if (( exitcode == 0 )); then + comm2=(unzip -q "$target" -d) + else + comm1=(echo "The utility 'unzip' is missing, please install it") + comm3=(exit 1) + fi +elif (( israr == 0 )); then + which unrar 1>/dev/null + exitcode=$? + if (( exitcode == 0 )); then + comm2=(unrar -i nul "$target") + else + comm1=(echo "The utility 'unrar' is missing, please install it") + comm3=(exit 1) + fi +fi + +# Create the temp dir, usually +dir=$(mktemp -d /tmp/extracted.XXXXXXXX) + +# And the rest of the commands +"${comm1[@]}" +"${comm2[@]}" $dir +"${comm3[@]}" + +cd $dir +echo "" +echo "Type 'exit' to exit the extracted archive's folder and auto-delete it" +eval $SHELL +rm -rf $dir diff --git a/daisy.source b/daisy.source new file mode 100755 index 0000000..67a5c10 --- /dev/null +++ b/daisy.source @@ -0,0 +1,394 @@ +#!/bin/echo "This file can only be sourced, not run stand-alone." -- #!/bin/bash +# LACKADAISICAL SOURCE-ABLE FILE + +# Source this in your RC file or manually to receive some of the simpler +# utilities, as well as aliases for `shrc` and `cdf`. Set env variable +# FROM_RC to 1 when sourcing this file to get RC-related functionality: +# FROM_RC=1 source /daisy.source +`` +# This file is also sourced in some of the scripts included within +# lackadaisical for common functionality. Some of the shared functionality is +# only included if sourced from one of the included scripts, though you are +# free to bypass this by setting env variable DAISY_INTERNAL to 1. + +[[ $DAISY_INTERNAL -eq 1 ]] && export DAISY_BIN=$(basename $0) + +# Intro function +function daisy_help() +{ + OLD_IFS="$IFS" + IFS= + echo -e "===================================================================" + echo -e "" + echo -e "Thanks for installing LACKADAISICAL!" + echo -e "This project aims to provide useful utilities as well as learning" + echo -e "material." + echo -e "It is still under heavy development, not all of the things on this" + echo -e "list are present/implemented." + echo -e "" + echo -e "===================================================================" + echo -e "" + echo -e "This suite provides a number of functions, aliases and scripts." + echo -e "They are all aimed at enhancing your efficiency." + echo -e "" + echo -e "===================================================================" + echo -e "" + echo -e "These are the included binaries:" + echo -e " - calm: Reduce a process niceness to 0." + echo -e " - chroot-aio: A chroot wrapper that also takes care of binding" + echo -e " every required directory and has no options." + echo -e " - cdz: This utility extracts an archive to /tmp and changes" + echo -e " directory to it in a new shell instance. Upon exit," + echo -e " the files are wiped." + echo -e " - editx: Uses your standard CLI editor to create/modify a" + echo -e " file and make it executable." + echo -e " - filewait: This tool is given a filename of a file that does" + echo -e " not exist yet. When the file appears on disk, the" + echo -e " program quits and simply returns the filename. This" + echo -e " can be used in personal workflows." + echo -e " - newday: A basic but powerful journaling system. Recommended" + echo -e " to set up via crontab. Can be used for everything" + echo -e " from diaries to BTRFS snapshots." + echo -e " - own: A simple utility. It effectively uses chown -R" + echo -e " user:user on its target. Root permissions required!" + echo -e " - short: This tool allows you to set up directory shortcuts." + echo -e " It enhances cd t to integrate itsef using its own" + echo -e " syntax. It is similar to wd." + echo -e " - shrc: This tool allows you to edit the RC file for your" + echo -e " shell in your preferred editor. After saving, the" + echo -e " file is sourced by your shell." + echo -e " - sw: A basic function that swaps two files by content." + echo -e " Useful for restoring backups." + echo -e " - what: This is a tool similar to which and others, the key" + echo -e " difference is that it returns partial matches. It can" + echo -e " be used to search for binaries." + echo -e "" + echo -e "===================================================================" + echo -e "" + echo -e "There are aliases and functions included within this file as well:" + echo -e " - bak/unbak: These small utilities make backups of files by making" + echo -e " a copy with a .bak suffix. Unbak reverses the process" + echo -e " using sw and removes the backup." + echo -e " - lsa: A simple alias for ls -lah." + echo -e " - lsn: A simple alias for ls -lah --sort=time --reverse." + echo -e " - editbin: An alias for editx $(which ). Saves on typing." + echo -e " - ched: Like chsh but for your editor (EDITOR env). A list" + echo -e " from which you can choose an installed editor" + echo -e " (CLI or GUI) is shown." + echo -e " - cdf: Use fzf to find a file and then cd to its location." + echo -e " - ldrc: Edits this file and source it, similarly to shrc." + echo -e " - daisy_init: Alias for directly sourcing this file from any" + echo -e " LACKADAISICAL binary. You may use this yourself." + echo -e " - daisy_cbin: Contains the name of the current LACKADAISICAL" + echo -e " binary being run." + echo -e " - daisy_enc: Converts a file/stdin to a base64 block that can be" + echo -e " decoded by passing the output(s) to daisy_dec." + echo -e " - *_multi: A version of daisy_enc that runs encodes multiple" + echo -e " files and outputs daisy_base64_data blocks to a file" + echo -e " or stdout." + echo -e " - daisy_dec: Converts daisy_base64_data blocks back to the form" + echo -e " it was in originally." + echo -e " - *_multi: A version of daisy_dec that runs on multiple input" + echo -e " blocks that are either stored in a file or stdin." + echo -e "" + echo -e "===================================================================" + echo -e "" + echo -e "To uninstall LACKADAISICAL, simply remove the source line from your" + echo -e "shell RC, and reload it. This does not remove the files!" + echo -e "" + echo -e "To read this notice again, call the function 'daisy_help'." + echo -e "" + echo -e "===================================================================" + + IFS="$OLD_IFS" +} + +# Variables for use in other utilities +# Find the right argument for our folder +ARG=$0 +if [[ ! $ARG == *daisy.source* ]]; +then + ARG="${BASH_SOURCE[0]}" +fi + +export DAISY_FOLDER=$(dirname $(realpath $ARG)) +export DAISY_SOURCE_FILE=$(realpath $ARG) +export DAISY_AVAILABLE=0 + +# Config folder setup +export DAISY_CONFIG_FOLDER="$HOME/.config/lackadaisical" +NEW_INSTALL=0 + +if [[ ! -d "$DAISY_CONFIG_FOLDER" ]]; +then + # Create the folder with its basics + mkdir -p "$DAISY_CONFIG_FOLDER" + echo "export EDITOR=$EDITOR" > "$DAISY_CONFIG_FOLDER/editor.src" + daisy_help + NEW_INSTALL=1 +fi + +# Installation into PATH +if [[ ! $PATH == *"$DAISY_FOLDER"* ]]; +then + export PATH="$PATH:$DAISY_FOLDER" + [[ NEW_INSTALL -eq 1 ]] && echo -e "Lackadaisical binaries have been added to your PATH variable." +fi + +# Load override from config (default is $EDITOR - so no change is made) +_EDITOR=$(cat "$DAISY_CONFIG_FOLDER"/editor.src | grep "EDITOR=" | sed 's/export EDITOR=//g') + +NEED_CHED=0 +if [[ -z $EDITOR ]]; +then + NEED_CHED=1 +fi + +# Never call if we're in internal mode +if [[ $DAISY_INTERNAL -eq 1 ]]; +then + NEED_CHED=0 +fi + +# Set up the basic alias for `shrc` +# Do not set these up if DAISY_INTERNAL=1 is set, or infinite recursion could +# occur! +if [[ ! -v DAISY_INTERNAL ]]; +then + alias shrc=". shrc" +fi + +############################################################################### +# FUNCTIONS and ALIASES ####################################################### +############################################################################### + +# bak and unbak +function bak() +{ + # Input: + target=$1 + + # Check if file exists + if ! test -f "$target"; + then + echo "Path not found: \"$target\"" + return 2 + fi + + # Handle both cases + if [[ UNBAK_MODE -eq 1 ]]; + then + cp -R "$target.bak" "$target" + rm -rf "$target.bak" + echo "Restored backup: $target <-- $target.bak" + else + cp -R "$target" "$target.bak" + echo "Backup made: $target --> $target.bak" + fi +} + +alias unbak="UNBAK_MODE=1 bak" +alias lsa="ls -lah" +alias lsn="ls -lah --sort=time --reverse" + +# Simple version of `cdf` +function cdf() +{ + cd $(dirname $(fzf)) +} + +# for convenience purposes +function editbin() +{ + editx $(which $1) +} + +# sets a new editor based on commony available ones, and some visual ones +function ched() +{ + editors=("nano" "vim" "nvim" "vi" "emacs" "gedit" "kate" "mousepad" "micro" \ + "code" "subl" "joe" "kwrite" "gnome-text-editor") + + # Find which editors are installed + available_editors=() + for editor in "${editors[@]}"; + do + EDITOR_REAL=$(which $editor) + if command -v "$EDITOR_REAL" >/dev/null 2>&1; + then + if [[ $(realpath "$EDITOR") == "$EDITOR_REAL" ]]; + then + available_editors+=("$editor (current choice)" "$EDITOR_REAL") + else + available_editors+=("$editor" "$EDITOR_REAL") + fi + fi + done + + if [[ ! -z $@ ]]; + then + TEXT="$@" + dialog --msgbox "$TEXT" 0 0 + fi + + # Present all choices + CHOICE=$(dialog --clear --title "Select Text Editor (Recommendation: nano)" \ + --menu "Choose one of the installed text editors:" 15 50 6 \ + "${available_editors[@]}" 3>&1 1>&2 2>&3) + DIALOG_RET=$? + + if [ $DIALOG_RET -ne 0 ]; + then + echo "No editor selected." + return + fi + + CHOICE=$(which $CHOICE) + echo export EDITOR=$CHOICE > "$DAISY_CONFIG_FOLDER/editor.src" + echo export DAISY_OLD_EDITOR=$EDITOR >> "$DAISY_CONFIG_FOLDER/editor.src" + + # Seems silly but this is also where we should export these + source "$DAISY_CONFIG_FOLDER/editor.src" +} + +function wait_for_editor() +{ + pname="$1" + fname="$2" + + # Give some time for a process to launch + sleep 1 + + while true; + do + ALIVE=$(ps aux | grep $fname | grep $pname) + if [[ $ALIVE == "" ]] + then + break + fi + sleep 1 + done +} + +function ldrc() +{ + FROM_RC=0 $EDITOR "$DAISY_SOURCE_FILE" + wait_for_editor $EDITOR "$DAISY_SOURCE_FILE" + source "$DAISY_SOURCE_FILE" +} + +function daisy_enc() +{ + has_file=$([[ ! -z $1 ]] && file $1 1>/dev/null; echo $?) + has_file=$([[ has_file -eq 0 ]] && echo 1) + file_info="no data" + file_name="null" + if [[ has_file -eq 1 ]]; + then + file_info=$(file $1) + file_name=$(basename $1) + fi + + data=$(cat ${1:-/dev/stdin}) + base64_inner=$(echo -e "$data" | base64 | tr '\n' '-') + + # Print out our block + printf "# File info: $file_info\n" + printf "daisy_data_base64_$file_name=\"$base64_inner\"" +} + +# Will only take input files, always outputs to stdout +function daisy_enc_multi() +{ + [[ ! -d $1 ]] && echo "daisy_dec_multi: No input files specified" && return + for file in "$@"; do + if [[ -f "$file" ]]; then + daisy_enc "$file" + echo # separate blocks with a newline + else + echo "daisy_enc_multi: Skipping non-file: $file" + fi + done +} + +function daisy_dec() +{ + data=$(cat ${1:-/dev/stdin} | sed -e 's/.*=\"//g' | grep -v "#" | tr -d '\"' | tr -d "'" | tr '-' '\n' ) + decoded=$(echo -e "$data" | cut -d "=" -f 1 | base64 --decode) + printf "$decoded" +} + +# Will only take a file and directory, sources it to find all encoded data +# Extracts to the directory +function daisy_dec_multi() +{ + [[ ! -f $1 ]] && echo "daisy_dec_multi: No input file specified" && return + [[ ! -d $2 ]] && echo "daisy_dec_multi: No output directory specified" && return + declare -a vars=( $(cat $1 | grep -v "# File") ) + for enc in "${vars[@]}"; + do + file=$(echo -e "$enc" | cut -d "_" -f 4- | cut -d "=" -f 1) + + if [[ ! "$file" == '' ]] + then + daisy_dec <(echo "$enc") | tee "$2"/"$file" + fi + done +} + +alias daisy_init='source "$DAISY_SOURCE_FILE"' + +############################################################################### +# end of FUNCTIONS and ALIASES ################################################ +############################################################################### +if [[ $NEED_CHED -eq 1 ]]; +then + # Editor is unset, pick one, set `vi` as backup + TXT1="There is no standard EDITOR environment variable defined. Choose one of the installed text editors." + TXT2="You can always change it later wih `ched`, part of the Lackadaisical suite." + ched $TXT1 $TXT2 +fi + +# End of user section! +export DAISY_AVAILABLE=1 + +# Start of internal section + +# Check for dependencies +function daisy_dependency_check() +{ + command -v $1 1>/dev/null 2>/dev/null; + res=$? + echo $(($res ^ 1)) +} + +DAISY_HAS_fzf=$(daisy_dependency_check fzf) +DAISY_HAS_md5sum=$(daisy_dependency_check md5sum) + +function daisy_quit_if_no() +{ + has_dep=$DAISY_HAS_$1 + + # Check first if we have checked for this dependency, if not, print a fixme! + # TODO: Remove upon release, or convert into self-modifying code. + if [[ ! -v DAISY_HAS_$1 ]]; + then + echo "FIXME: Dependency `$1` should have an env variable, checking ad-hoc" + has_dep=$(daisy_dependency_check $1) + fi + + if [[ $has_dep -eq 0 ]]; + then + echo "$DAISY_BIN: The dependency $1 was not found! Please install it" \ + "to be able to use this utility!" + exit 1 + fi +} + +[ -d "$DAISY_FOLDER" ] && export DAISY_AVAILABLE=1 + +# Source everything in the config folder +# We do this at the end so that we do not run into isues +for file in "$DAISY_CONFIG_FOLDER"/*; do + [ -f "$file" ] && source "$file" +done diff --git a/editx b/editx new file mode 100755 index 0000000..39e7810 --- /dev/null +++ b/editx @@ -0,0 +1,27 @@ +# !/bin/bash +# This utility pre-allocs a file and adds execution permissions. It also +# removes the resulting file if it is empty after the editor closes. + +if [[ -z $1 ]]; +then + echo "No filename specified." + exit 2 +fi + +if [[ -z "${EDITOR}" ]]; +then + ched "EDITOR env variable not set! You will have to set it yourself in the next screen." +fi + +exists=$(file "$1" >/dev/null && echo $?) + +touch "$1" +chmod +x "$1" +$EDITOR "$1" +wait $! +SIZE=$(du "$1" | cut -f 1) + +if [[ $SIZE -eq 0 && $exists -ne 0 ]]; +then + rm -rf "$1" +fi diff --git a/filewait b/filewait new file mode 100755 index 0000000..f00e554 --- /dev/null +++ b/filewait @@ -0,0 +1,8 @@ +#!/bin/bash +# A simple utility that waits for a file to become available, infinitely +FILE=$@ +while [ ! -f "$FILE" ] +do + sleep 0.1 +done +echo $FILE diff --git a/newday b/newday new file mode 100755 index 0000000..d6586f2 --- /dev/null +++ b/newday @@ -0,0 +1,52 @@ +#!/bin/bash +# This script is intended to be run via cron. + +# It creates a folder structure in home for the current date in the following format: +# $HOME/ByDate/// + +# It also sets up a symlink in home: $HOME/Today +# This symlink will always point to the folder for the current date. + +# Finally, it removes any folders without data, to prevent clutter. + +# - Why did you make this? +# I remember things better when they have a date attached to them. +# You can use this for a primitive form of note-taking, but aside from notes - +# you can store any data this way. + +BINSELF=$(basename $0) +DIR_NAME=ByDate +ROOT_DIR=$HOME/$DIR_NAME +TODAY_SYM=$HOME/Today + +# Present day +TODAY=$(date --iso-8601) +YEAR=$(echo $TODAY | awk -F"-" '{print $1}') +MONTH=$(echo $TODAY | awk -F"-" '{print $2}') +DAY=$(echo $TODAY | awk -F"-" '{print $3}') + +set -e + +function errorFn() +{ + ERROR=$? + if [[ $ERROR -gt 0 ]]; + then + echo "$BINSELF error ($ERROR): " + perl -E 'say $!=shift' $ERROR + fi + exit $ERROR +} + +# Error handling +trap errorFn ERR + +# First we clear out empty folders, and remove the symlink if it exists +test -e "$ROOT_DIR" && find "$ROOT_DIR" -maxdepth 3 -type d -empty -print | xargs rm -rf +test -L "$TODAY_SYM" && rm -rf "$TODAY_SYM" + +# Now we can set up today's directory +mkdir -p "$ROOT_DIR/$YEAR/$MONTH/$DAY" +cd $ROOT_DIR +ln -s "./$DIR_NAME/$YEAR/$MONTH/$DAY" "$TODAY_SYM" + diff --git a/own b/own new file mode 100755 index 0000000..bc030e3 --- /dev/null +++ b/own @@ -0,0 +1,4 @@ +#!/bin/sh +# Simple program that changes ownership to the current +# user, recursively. +sudo chown -R $(whoami):$(whoami) $1 diff --git a/short b/short new file mode 100755 index 0000000..d637e39 --- /dev/null +++ b/short @@ -0,0 +1,19 @@ +#!/bin/bash +# short: Creates shortcuts that can be used anywhere. +# Can also be used as an alternative for "alias". +# +# Example usage: +# Add a shortcut: short -A dev "/home/john/Development" +# Print shortcut content: short dev -> "/home/john/Development" +# Remove shortcut: short -D dev +# +# One could use this to do things like: +# cp -R files $(short dev) +# cd $(short www) +# ssh $(short server) +# +# Uses a file named .shortcuts in $HOME + +SHORT_FILE=$HOME/.shortcuts + + diff --git a/shrc b/shrc new file mode 100755 index 0000000..4c3342b --- /dev/null +++ b/shrc @@ -0,0 +1,47 @@ +#!/bin/echo Please run this program with: ". shrc" or include +# `FROM_RC=1 source shrc` in your RC file to set up an alias. + +# Just opens your .rc file easily, for your current shell +# and sources the .rc afterwards! + +# Source standard setup +if [[ $DAISY_INTERNAL -ne 1 ]]; +then + DAISY_INTERNAL=1 source $DAISY_SOURCE_FILE +fi + +function md5_opt() +{ + if [[ $DAISY_HAS_md5sum -eq 1 ]]; + then + echo $(md5sum "$1" | awk '{print $1}') + fi +} + +if [[ $FROM_RC -eq 1 ]]; then + alias shrc=". shrc" +else + BASENAME=$(basename $SHELL) + RC_NAME="."$BASENAME"rc" + RC_PATH="$HOME/$RC_NAME" + + # Optional MD5 checks + HAS_CHANGED=1 + SUM1=$(md5_opt "$RC_PATH") + SUM2= + + # This sets a default if the variable does not exist. + EDITOR=${EDITOR:-$(ched)} + $EDITOR "$RC_PATH" + wait_for_editor $EDITOR "$RC_PATH" + + SUM2=$(md5_opt "$RC_PATH") + + if [[ $DAISY_HAS_md5sum -eq 1 && "$SUM1" == "$SUM2" ]]; + then + echo "The RC-file $RC_NAME has not changed on disk. Not sourcing." + return + fi + + source "$RC_PATH" +fi diff --git a/sw b/sw new file mode 100755 index 0000000..6bf5cb5 --- /dev/null +++ b/sw @@ -0,0 +1,42 @@ +#!/bin/sh +# It just swaps two files +' +FILE1=$1 +FILE2=$2 + +function helpFn() +{ + ERROR=$? + if [[ $ERROR -gt 0 ]]; + then + echo "$BINSELF error ($ERROR): " + perl -E 'say $!=shift' $ERROR + fi + echo "Usage: $BINSELF " + echo Swap two files in a filesystem. + exit $ERROR +} + +if [[ $@ == *"--help"* ]]; +then + helpFn +fi + +# We set a trap here, together with 'set -e' above, +# this makes sure we exit gracefully if we have an +# error in one of the ls or mv calls. +trap helpFn ERR + +# We want to swap two files +# Easy, but let's be safe about it +ls "$FILE1" >/dev/null +ls "$FILE2" >/dev/null + +# Files should exist, now we move +mv "$FILE1" "$FILE1.sw" +mv "$FILE2" "$FILE2.sw" + +# We got our moved copies, now we simply rename +mv "$FILE1.sw" "$FILE2" +mv "$FILE2.sw" "$FILE1" + diff --git a/what b/what new file mode 100755 index 0000000..3df74d7 --- /dev/null +++ b/what @@ -0,0 +1,29 @@ +#!/bin/sh +# Where is the binary? +# Usage: what [] +# Returns: +# With no parameters, all visible binaries in PATH. +# With parameter, all binaries that match the pattern +# given. Accepts default grep patterns, case insensitive +# +# Examples: +# $ what zs.* +# pzstd +# zsh +# zstd +# +# $ what ftp +# ftppass +# sftp +# vsftpd +# +# $ what ftp | xargs which +# /usr/bin/ftppass +# /usr/bin/sftp +# /usr/sbin/vsftpd +# + +PWD=/ +ALL_BINS=$(cd / && echo $PATH | sed 's/[:]/ /g' | xargs ls -A | grep -v ":" | sort | uniq) +OUTPUT=$(printf '%s\n' "-n" $ALL_BINS | grep -i "$1") +echo "$OUTPUT"