Last active
June 18, 2024 09:15
-
-
Save Stewie410/a5da07849e57fd264592168679d2d6b9 to your computer and use it in GitHub Desktop.
TheOuterLinux 'bashrc - basic.txt' Overhaul
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| #!/usr/bin/env bash | |
| # bashtask | |
| alias bashtask='bashtask.sh' | |
| alias taskadd='bashtask --add' | |
| alias taskin='bashtask --insert' | |
| alias taskrm='bashtask --remove' | |
| alias taskcl='bashtask --clear' | |
| alias tasklist='bashtask --print' | |
| # Find out what is taking so much space on your drives | |
| alias diskspace='du --separate-dirs | sort --numeric-sort --reverse | less' | |
| #Create password protected .7z compressed file and hide file-list | |
| #Use as: 7zp "/path/to/output.7z" "/path/to/folder_or_file" | |
| alias 7zp='7z a -bd -bb1 -y -p -mhe=on -mx=7' | |
| # Quickly jump 1-4 directories up | |
| alias ..="cd .." | |
| alias ...="cd ../.." | |
| alias ....="cd ../../.." | |
| alias .....="cd ../../../.." | |
| # Common variations of 'ls' command | |
| alias ll='ls -l' | |
| alias lo='ls -o' | |
| alias lh='ll --human-readable' | |
| alias la='ll --all' | |
| alias sl='ls' | |
| alias l='ls' | |
| alias s='ls' | |
| #Nano for writing and help with spell-checking | |
| alias nano='nano --mouse --unix --constantshow --wordbounds --tabsize=4 --autoindent' | |
| alias writer='nano --fill=85 --smooth' | |
| #The following is for spellchecking SGML/XML-like documents of project | |
| #files. 'Scribus' is a free and open-source desktop publishing program. | |
| alias spellcheck='aspell -c' | |
| alias spellcheckgsml='aspell --lang=en --encoding=utf-8 --mode=sgml --add-sgml-check=ch check' | |
| alias spellcheckxml='spellchecksgml' | |
| alias spellcheckscribus='spellchecksgml' | |
| #Print the last line of all logs within the "/var/log" directory | |
| alias logs='find "/var/log" -type f -exec grep --binary-files="without-match" --quiet "." {} \; -print | xargs tail --follow' | |
| # Git related | |
| alias gs='git status' | |
| alias gc='git commit' | |
| alias ga='git add' | |
| alias gd='git diff' | |
| alias gb='git branch' | |
| alias gl='git log' | |
| alias gsb='git show-branch' | |
| alias gco='git checkout' | |
| alias gg='git grep' | |
| alias gk='gitk --all' | |
| alias gr='git rebase' | |
| alias gri='git rebase --interactive' | |
| alias gcp='git cherry-pick' | |
| alias grm='git rm' | |
| #For when you've spent too much time in DOS | |
| alias cls='clear' | |
| alias dir='ls' | |
| alias deltree='rm --recursive' | |
| alias rmdir='deltree' | |
| alias rd='deltree' | |
| alias rename='mv' | |
| alias cd..='cd ..' | |
| alias chdir='pwd' | |
| alias cmd='bash' | |
| alias erase='rm' | |
| alias del='rm' | |
| alias delete='rm' | |
| alias expand='extract' | |
| alias tasklist='htop' | |
| alias tracert='traceroute' | |
| #Expand current directory structure in tree form | |
| alias treed='tree -R' | |
| #Uses 'nmap' to scan all of the connected devices on your router | |
| #You may need to change the '192.168.0.*' part to better match how your | |
| #router gives addresses. This will most likely not give you hostnames, | |
| #only MAC addresses. | |
| alias lanscan='sudo nmap -sn 192.168.0.*' | |
| #Use one of the following for when the boss comes around to look busy... | |
| #But remember, as mentioned before, the /dev/urandom may cause some | |
| #serious slow-down issues on older/lighter hardware. | |
| alias busy='hexdump -C "/dev/urandom" | grep "ca fe"' | |
| #Print last value returned from previous command | |
| alias lastvalue='printf "%s\n" "$?"' | |
| #Create a randomized playlist for audio and video recursively | |
| # | |
| # Usage: playlist > playlist.m3u | |
| # | |
| alias playlist='find -D tree . | sort --random-sort --random-source="/dev/urandom"' | |
| #Optimize mpv for playing just about anything without having to think | |
| #too much; 720p is chosen because of older hardware | |
| alias mpv='mpv --vo=opengl,x11,drm,tct,caca --ao=pulse,alsa,jack --user-agent="Mozilla" --ytdl-format="best[ext=mp4][height<=?720]"' | |
| #Nerd humor; use 'zardoz' instead of 'sudo' | |
| alias zardoz='sudo' | |
| #Day-mode...Ooooh aaaAAAh! Enemy of the nightmode... Ooooh aaaAAAh! | |
| #Use daymode/nightmode to toggle the a red screen tint on/off for doing | |
| #things such as Astronomy. | |
| alias daymode='xgamma -gamma 1' | |
| alias nightmode='xgamma -rgamma 1 -ggamma 0.3 -bgamma 0.3' | |
| #Quickly open a color picker using 'GPick' that copies clicked color to | |
| #the clipboard. Though, you could argue that it isn't much of a shortcut | |
| #based on text length... | |
| alias cgrab='gpick --pick' | |
| #Grab audio only from YouTube | |
| # Usage: yta-mp3 https://youtube.com/watch?v=??????????? | |
| # | |
| # You could also replace youtube-dl with 'yt-dlp' as they both more or | |
| # less use the same arguments. | |
| # | |
| alias yta-aac='youtube-dl --extract-audio --audio-format aac' | |
| alias yta-best='youtube-dl --extract-audio --audio-format best' | |
| alias yta-flac='youtube-dl --extract-audio --audio-format flac' | |
| alias yta-m4a='youtube-dl --extract-audio --audio-format m4a' | |
| alias yta-mp3='youtube-dl --extract-audio --audio-format mp3' | |
| alias yta-opus='youtube-dl --extract-audio --audio-format opus' | |
| alias yta-vorbis='youtube-dl --extract-audio --audio-format vorbis' | |
| alias yta-wav='youtube-dl --extract-audio --audio-format wav' | |
| #Grab the highest quality of video+audio from YouTube | |
| alias ytv-best='youtube-dl -f bestvideo+bestaudio' | |
| #Because I got tired of typing 'w3m https://duckduckgo.com'... | |
| alias ddg='w3m duckduckgo.com' | |
| #Add some flags to some basic commands that probably should be default | |
| #The aliases below with '--interactive' refer to asking for confirmation before | |
| #doing things with files; rm needs to have three or more files or have | |
| #the '--recursive' flag involved before asking for confirmation to delete. | |
| alias cp='cp --interactive' | |
| alias mv='mv --interactive' | |
| alias rm='rm --interactive' | |
| alias ln='ln --interactive' | |
| alias df='df --human-readable' | |
| alias free='free --mebi' | |
| alias mkdir='mkdir --parents --verbose' | |
| # Some 'ps' command aliases... | |
| alias psa='ps auxf' | |
| alias psgrep='pgrep --full --list-full' | |
| alias psmem='ps auxf | sort --numeric-sort --reverse --key="4"' | |
| alias pscpu='ps auxf | sort --numeric-sort --reverse --key="3"' | |
| #Have the 'mocp' command-line music player use the nightly_theme | |
| #Default themes are located within "/usr/share/moc/themes/" | |
| alias mocp='mocp --theme "nightly_theme"' | |
| #Converting audio and video files using ffmpeg and eyeD3 | |
| #(sudo pip install eyeD3). Album art is removed in the '2ogg' function | |
| #because if you are using ogg, you probably either do not need it or | |
| #want to save as much space as possible. The '2voc' is very useful when | |
| #dealing with DOOM WADS or certain DOS software. If you need to cancel a | |
| #conversion that uses FFmpeg, use CTRL+C as 'q' will still delete the | |
| #original and then leave you with a partially converted file. If you | |
| #hate the idea of deleting the original file, remove the '&& rm "$1"' | |
| #parts at the end. | |
| # | |
| # Usage example: 2ogg '/path/to/file.ext' | |
| # | |
| alias ff-conv='media_convert.sh --delete' | |
| alias 2ogg='ff-conv --remove-images --format ogg' | |
| alias 2wav='ff-conv --format wav' | |
| alias 2opus='ff-conv --format opus' | |
| alias 2aif='ff-conv --format aif' | |
| alias 2mp3='ff-conv --format mp3' | |
| alias 2mov='ff-conv --format mov' | |
| alias 2mp4='ff-conv --format mp4' | |
| alias 2avi='ff-conv --format avi' | |
| alias 2webm='ff-conv --format webm' | |
| alias 2h265='ff-conv --format h265' | |
| alias 2flv='ff-conv --format flv' | |
| alias 2mpg='ff-conv --format mpg' | |
| alias 2doswav8='ff-conv --format doswav --eight' | |
| alias 2doswav11='ff-conv --format doswav' | |
| alias 2doswav='2doswav11' | |
| alias 2voc8='ff-conv --format voc --eight' | |
| alias 2voc11='ff-conv --format voc' | |
| alias 2voc='2voc11' | |
| #The following are for converting a video to a DVD-ready MPEG format | |
| #for faster use with DVD creation programs. Use the "sub" versions | |
| #below to permanently overlay subtitles (*.srt) onto the video. The | |
| #output is automatically handled for you by placing the file in the same | |
| #directory with the same name but with "_NTSC" or "_PAL" appended to the | |
| #end. The original is deleted when finished so make shure to use Ctrl+c | |
| #if canceling the conversion to prevent deleting the original as | |
| #previously mentioned in the above other "2[format]" video conversions. | |
| # | |
| # Normal usage example: 2mpgNTSC input.ext | |
| # Usage for subtitle overlay example: 2mpgNTSCsub input.srt input.ext | |
| # | |
| alias 2mpgNTSC='ff-conv --format mpg --ntsc' | |
| alias 2mpgNTSCsub='2mpgNTSC --subtitles' | |
| alias 2mpgPAL='ff-conv --format mpg --pal' | |
| alias 2mpgPALsub='2mpgPAL --subtitles' | |
| #Converting documents and images using pandoc | |
| # | |
| # Usage example: 2pdf '/path/to/file.html' | |
| # Usage example: 2pdf '/path/to/file.html' '/path/to/file.pdf' | |
| # | |
| alias p-conv='office_convert.sh --delete' | |
| alias 2txt='p-conv --format txt' | |
| alias 2pdf='p-conv --format pdf' | |
| alias 2doc='p-conv --format doc' | |
| alias 2odt='p-conv --format odt' | |
| #Convert images using ImageMagick | |
| # | |
| # Usage example: 2jpg '/path/to/image.ext' | |
| # | |
| alias im-conv='image_convert.sh --delete' | |
| alias 2pcx='im-conv --format pcx' | |
| alias 2lbm='im-conv --format ilbm' | |
| alias 2jpg='im-conv --format jpg' | |
| alias 2jpeg='2jpg' | |
| alias 2png='im-conv --format png' | |
| alias 2png8='im-conv --format png8' | |
| alias 2bmp='im-conv --format bmp' | |
| alias 2dosbmp='im-conv --format dosbmp' | |
| alias 2dosgif='im-conv --format dosgif' | |
| alias 2tiff='im-conv --format tiff' | |
| alias 2ico='im-conv --format ico' | |
| #Quickly use QEMU, if installed, to boot a 64-bit, i686/i586, or i486 | |
| #operating system from an ISO | |
| alias bootiso='qemu_boot.sh' | |
| alias boot32='bootiso --i686' | |
| alias boot486='bootiso --i486' | |
| #Potentially lower an image's file size using ImageMagick by lowering | |
| #the amount of colors, using dithering, increasing contrast, etc... | |
| # | |
| # Usage: optimg '/path/to/image.ext' | |
| # | |
| alias optimg='im-conv --optimize' | |
| #Potentially lower a PDF's file size using Ghostscript | |
| # | |
| # Usage: optpdf '/path/to/file.pdf' | |
| # | |
| alias optpdf='ff-conv --optimize' | |
| alias optpdf72='ff-conv --optimize --dpi 72' | |
| alias optpdf96='ff-conv --optimize --dpi 96' | |
| alias optpdf300='ff-conv --optimize --dpi 300' | |
| #Convert a PDF to a different version; pdfto11 = 1.1; pdfto12 = 1.2; etc... | |
| # | |
| # Usage Example: pdfto13 input.pdf output.pdf | |
| # | |
| alias pdfto11='pdf_version.sh --version "1.1"' | |
| alias pdfto12='pdf_version.sh --version "1.2"' | |
| alias pdfto13='pdf_version.sh --version "1.3"' | |
| alias pdfto14='pdf_version.sh --version "1.4"' | |
| alias pdfto15='pdf_version.sh --version "1.5"' | |
| alias pdfto16='pdf_version.sh --version "1.6"' | |
| alias pdfto17='pdf_version.sh --version "1.7"' | |
| alias pdfto20='pdf_version.sh --version "2.0"' | |
| #Append line numbers to the beginning of each line | |
| # | |
| # Usage: addlinenumbers '/path/to/file.txt' | |
| # Make permanent: addlinenumbers input.txt | tee output.txt | |
| # | |
| alias addlinenumbers='nl --number-format="ln"' | |
| #Use webcam as a timelapse camera | |
| alias timelapse='timelapse.sh' | |
| # Internet speed test using speedtest-cli | |
| alias int-speed='speedtest' | |
| #Zip all files in current directory INDEpendently from each other; in | |
| #other words, each file gets its own zip. | |
| # | |
| # Usage: cd /path/to/directory && indezip | |
| # | |
| alias indezip='independent_zip.sh' | |
| #Zip all files in current directory independently from each other AND | |
| #delete the originals when finished. | |
| # | |
| # Usage: cd /path/to/directory && indeziprm | |
| # | |
| alias indeziprm='indezip --delete' | |
| #Get the mime information (file-type) of a file | |
| #For example, a plain text file would have 'text/plain' as the mime | |
| # | |
| # Usage: mime /path/to/file.ext | |
| # | |
| alias mime='file --mime-type' | |
| #Convert a bunch of PNG's or JPEG's to video. | |
| #I have two separate functions for JPG and JPEGs, even | |
| #though they are the same format. Someone out there may be taking | |
| #advantage of this and have JPGs that "stand for" one thing and then use | |
| #the JPEG extension for some other purpose. | |
| # | |
| # Usage example B: cd /path/to/PNG/directory && png2video [framerate] output.mp4 | |
| # Usage example C: cd /path/to/JPG/directory && jpg2video [framerate] output.mp4 | |
| # Usage example D: cd /path/to/JPEG/directory && jpeg2video [framerate] output.mp4 | |
| # | |
| alias png2video='stitch_frames.sh --format "png"' | |
| alias jpg2video='stitch_frames.sh --format "jpg"' | |
| alias jpeg2video='stitch_frames.sh --format "jpeg"' | |
| #Use wget to download everything listed within a plain-text file | |
| # | |
| # Usage: grablist /path/to/URL_List.txt | |
| # | |
| alias grablist='wget --continue --content-disposition --trust-server-names -i' | |
| #Use this to grap all of the files with the "$2" extension recursively | |
| #from a website, or at least the sensible ones that let you crawl around | |
| #in directories. | |
| # | |
| # Example: dlext "*.mp3" https://exmaple.org | |
| # | |
| alias dlext='wget --recursive --no-parent --level="1" --accept' | |
| #Use this to grab all of the ZIP files recursively from a website | |
| alias dlzips='dlext "*.zip"' |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| #!/usr/bin/env bash | |
| # Generate a psuedo-random password | |
| # Though, I cannot stress this enough: use a dedicated tool, like: | |
| # - pwgen | |
| # - bw | |
| # - keepassxc | |
| genpasswd() { | |
| if [[ "${1}" =~ -(h|-help) ]]; then | |
| printf '%s\n' "USAGE: ${FUNCNAME[0]} [-h|--help]" | |
| return 0 | |
| fi | |
| local pw | |
| pw="$(LC_ALL="C" tr \ | |
| --delete \ | |
| --complement \ | |
| "A-Za-z0-9!\"#$%&'()*+,-./:;<>=?@[\]^_\`{|}~" < "/dev/urandom" | \ | |
| head --bytes="30" \ | |
| )" | |
| printf '%s\n' "${pw}" | |
| } | |
| #Create a .7z compressed file; though, I am not saying '7z a...' is not | |
| #easy enough to do but for some people, maybe not because of putting | |
| #the output file before the input. | |
| #Use as: 7zip "/path/to/folder_or_file" "/path/to/output.7z" | |
| 7zip() { | |
| if [[ -z "${1}" || "${1}" =~ -(h|-help) ]]; then | |
| printf '%s\n' "USAGE: ${FUNCNAME[0]} [OPTIONS] SOURCE [DESTINATION]" | |
| return 0 | |
| fi | |
| 7z a \ | |
| -t7z \ | |
| -m0=lzma \ | |
| -mx=9 \ | |
| -mfb=64 \ | |
| -md=32m \ | |
| -ms=on \ | |
| -mhe=on \ | |
| "${2:-${1##*/}.7z}" "${1}" | |
| } | |
| # Move 'up' so many directories instead of using several cd ../../, etc. | |
| # Use as: up # | |
| up() { | |
| if [[ -z "${1}" || "${1}" =~ -(h|-help) ]]; then | |
| printf '%s\n' "USAGE: ${FUNCNAME[0]} [-h|--help] NUM" | |
| return 0 | |
| fi | |
| local path | |
| path="$(printf '../%.0s' $(seq 1 "${1}"))" | |
| cd "$(realpath "${path}")" && pwd | |
| } | |
| #List people in a Twitch channel chat | |
| twitch_list() { | |
| if [[ -z "${1}" || "${1}" =~ -(h|-help) ]]; then | |
| printf '%s\n' "USAGE: ${FUNCNAME[0]} [-h|--help] CHANNEL" | |
| return 0 | |
| fi | |
| curl \ | |
| --silent \ | |
| --fail \ | |
| --location \ | |
| "https://tmi.twitch.tv/group/user/${1}/chatters" | |
| } | |
| function spell() { echo "$1" | aspell -a; } | |
| # Print a word from a certain column of the output when piping. | |
| # Example: cat /path/to/file.txt | fawk 2 | |
| # This example prints every 2nd word on each line of file.txt | |
| fawk() { | |
| if [[ -z "${1}" || "${1}" =~ -(h|-help) ]]; then | |
| printf '%s\n' "USAGE: ${FUNCNAME[0]} [-h|--help] NUM" | |
| return 0 | |
| fi | |
| awk --assign "idx=${1}" '{print $idx}' | |
| } | |
| # 'cd' to the most recently modified directory in $PWD | |
| cl() { | |
| if [[ "${1}" =~ -(h|-help) ]]; then | |
| printf '%s\n' "USAGE: ${FUNCNAME[0]} [-h|--help]" | |
| return 0 | |
| fi | |
| local last_dir | |
| last_dir="$(find "${PWD}" -mindepth 1 -maxdepth 1 -type d -printf '%T@ %p\n' 2>/dev/null | \ | |
| sort --numeric-sort --reverse | \ | |
| cut --fields="2-" --delimiter=" " | \ | |
| sed 1q \ | |
| )" | |
| cd "${last_dir}" || return 1 | |
| } | |
| # Directory bookmarking (one at a time) | |
| remember_directory() { | |
| local opts action bufhome buf | |
| opts="$(getopt \ | |
| --options hlg \ | |
| --longoptions help,list,goto \ | |
| --name "${FUNCNAME[0]}" \ | |
| -- "${@}" \ | |
| )" | |
| action="save" | |
| bufhome="${XDG_STATE_HOME:-${HOME}/.cache}/${FUNCNAME[0]}" | |
| eval set -- "${opts}" | |
| while true; do | |
| case "${1}" in | |
| -h | --help ) | |
| cat << EOF | |
| Save current directory to numbered "buffers", or move to a previously saved directory | |
| USAGE: ${FUNCNAME[0]} [OPTIONS] NUM | |
| -h, --help Show this help message | |
| -l, --list List all directories stored in current buffers | |
| -g, --goto Move to directory saved in buffer NUM | |
| EOF | |
| return 0 | |
| ;; | |
| -l | --list ) action="list";; | |
| -g | --goto ) action="goto";; | |
| -- ) shift; break;; | |
| * ) break;; | |
| esac | |
| shift | |
| done | |
| if [[ "${action}" != "list" && -z "${1}" ]]; then | |
| printf '%s\n' "No buffer specified" >&2 | |
| return 1 | |
| fi | |
| mkdir --parents "${bufhome}" | |
| case "${action}" in | |
| list ) | |
| while read -r buf; do | |
| printf '%s: %s\n' "${buf##*/}" "$(< "${buf}")" | |
| done < <(find "${bufhome}" -type f | sort --numeric-sort) | |
| ;; | |
| goto ) | |
| cd "$(< "${bufhome}/${1}")" || return 1 | |
| ;; | |
| * ) | |
| printf '%s\n' "${PWD}" > "${bufhome}/${1}" | |
| ;; | |
| esac | |
| return 0 | |
| } | |
| rd() { | |
| remember_directory "${@}" | |
| } | |
| crd() { | |
| remember_directory --goto "${@}" | |
| } | |
| # 'cd' into a directory and then list contents | |
| cdls() { | |
| if [[ -z "${1}" || "${1}" =~ -(h|-help) ]]; then | |
| printf '%s\n' "USAGE: ${FUNCNAME[0]} [-h|--help] PATH" | |
| return 0 | |
| fi | |
| cd "${1}" && ls "${1}" | |
| } | |
| #For when you've spent too much time in DOS | |
| edit() { | |
| if [[ -z "${1}" || "${1}" =~ -(h|-help) ]]; then | |
| printf '%s\n' "USAGE: ${FUNCNAME[0]} [-h|--help] FILE" | |
| return 0 | |
| fi | |
| nano \ | |
| --mouse \ | |
| --unix \ | |
| --constantshow \ | |
| --breaklonglines \ | |
| --linenumbers \ | |
| --tabsize="4" \ | |
| --file="72" \ | |
| --atblanks \ | |
| --autoindent \ | |
| "${1}" || return | |
| sed -i'' 's/\n/\r\n/g' "${1}" | |
| } | |
| diskcopy() { | |
| if [[ -z "${1}" || "${1}" =~ -(h|-help) ]]; then | |
| printf '%s\n' "USAGE: ${FUNCNAME[0]} [-h|--help] SOURCE DESTINATION" | |
| return 0 | |
| fi | |
| if [[ -z "${2}" ]]; then | |
| printf '%s\n' "No destination specified" >&2 | |
| return 1 | |
| fi | |
| if ! [[ -b "${1}" ]]; then | |
| printf '%s\n' "Source is not a block device: '${1}'" >&2 | |
| return 1 | |
| fi | |
| if ! [[ -b "${2}" ]]; then | |
| printf '%s\n' "Destination is not a block device: '${2}'" >&2 | |
| return 1 | |
| fi | |
| dd if="${1}" of="${2}" | |
| } | |
| #List directories by in order of size in current directory | |
| sbs() { | |
| if [[ -n "${1}" ]]; then | |
| printf '%s\n' "USAGE: ${FUNCNAME[0]} [-h|--help]" | |
| return 0 | |
| fi | |
| du --human-readable --max-depth "1" 2>/dev/null | \ | |
| sort --reverse --human-numeric-sort --key="1" | |
| } | |
| #Kill any lingering SSH processes | |
| sshkill() { | |
| if [[ -n "${1}" ]]; then | |
| printf '%s\n' "USAGE: ${FUNCNAME[0]} [-h|--help]" | |
| return 0 | |
| fi | |
| killall --quiet "ssh" | |
| } | |
| #Rough function to display the number of unread emails in your gmail; | |
| #HOWEVER, I am Google-free these days, so I have no idea if this still | |
| #works... | |
| # | |
| # Usage: gmail [user name] | |
| # | |
| gmail() { | |
| if [[ -z "${1}" || "${1}" =~ -(h|-help) ]]; then | |
| printf '%s\n' "USAGE: ${FUNCNAME[0]} EMAIL" | |
| return 0 | |
| fi | |
| curl --user "${1}" --silent 'https://mail.google.com/mail/feed/atom' | \ | |
| sed 's|</fullcount.*|\n|;s|.*fullcount>||' | |
| } | |
| #Use one of the following for when the boss comes around to look busy... | |
| #But remember, as mentioned before, the /dev/urandom may cause some | |
| #serious slow-down issues on older/lighter hardware. | |
| busytext() { | |
| if [[ -n "${1}" ]]; then | |
| printf '%s\n' "USAGE: ${FUNCNAME[0]} [-h|--help]" | |
| return 0 | |
| fi | |
| while true; do | |
| head "/dev/urandom" | \ | |
| tr --delete --complement 'A-Za-z0-9' | |
| sleep '0.15' | |
| done | |
| } | |
| #If input is a video, convert use '2gif' to created an animated | |
| #(89a) GIF; otherwise, use ImageMagick to create a still (87a) GIF. | |
| # | |
| # Usage example: 2gif '/path/to/image/or/video.ext' | |
| # | |
| 2gif() { | |
| if [[ -z "${1}" || "${1}" =~ -(h|-help) || ! -s "${1}" ]]; then | |
| printf '%s\n' "USAGE: ${FUNCNAME[0]} [-h|--help] INPUT [OUTPUT]" | |
| return 0 | |
| fi | |
| if file --mime "${1}" | grep --quiet "image"; then | |
| image_convert --delete --format "gif" "${@}" || return 1 | |
| else | |
| media_convert --delete --format "gif" "${@}" || return 1 | |
| fi | |
| return 0 | |
| } | |
| #Tonvid is a YouTube frontend and this helps for when copy/paste text | |
| #isn't possible as you only need to type the video ID. | |
| # | |
| # Usage: tonvid [video ID] | |
| # | |
| tonvid() { | |
| if [[ -z "${1}" || "${1}" =~ -(h|-help) ]]; then | |
| printf '%s\n' "USAGE: ${FUNCNAME[0]} [-h|--help] TONVID_ID" | |
| return 0 | |
| fi | |
| if ! command -v "mpv" &>/dev/null; then | |
| printf '%s\n' "Missing required application: 'mpv'" >&2 | |
| return 1 | |
| fi | |
| mpv \ | |
| --vo='opengl,x11,drm,tct,caca' \ | |
| --ao='pulse,alsa' \ | |
| --ytdl-format='[ext=mp4][height<=?720]' \ | |
| "https://tonvid.com/info.php?video_id=${1}" | |
| } | |
| #Grab a pretty ascii forecast picture for anywhere; without arguments, | |
| #uses ISP location to print your weather. Example: weather New York, NY | |
| weather() { | |
| if [[ "${1}" =~ -(h|-help) ]]; then | |
| printf '%s\n' "USAGE: ${FUNCNAME[0]} [-h|--help] [QUERY]" | |
| curl --silent "wttr.in/:help" | |
| return 0 | |
| fi | |
| curl --silent "wttr.in/${*}" | |
| } | |
| #Grab weather information from USAirNet and have a pretty Wttr.in ascii | |
| #output. Example: weather 02118 boston | |
| weatherus() { | |
| if [[ -z "${1}" || "${1}" =~ -(h|-help) ]] || (( $# < 2 )); then | |
| printf '%s\n' "USAGE: ${FUNCNAME[0]} [-h|--help] ZIPCODE CITYNAME" | |
| return 0 | |
| fi | |
| if ! command -v "w3m" &>/dev/null; then | |
| printf '%s\n' "Missing required application: 'w3m'" >&2 | |
| return 1 | |
| fi | |
| # *Surely* there's an RSS feed or something to provide better results | |
| # without relying on w3m's plain-text dump... | |
| w3m -M -dump "http://www.usairnet.com/weather/forecast/local/?pands=${1}" | \ | |
| grep --after-context="10" --color="never" "${2^^}" | |
| printf "\n" | |
| weather "${2}" | |
| } | |
| #Convert hex data file to a binary | |
| function hex2bin() { | |
| if [[ "${1}" =~ -(h|-help) ]]; then | |
| printf '%s\n' "USAGE: ${FUNCNAME[0]} [-h|--help] [HEXFILE]" | |
| return 0 | |
| fi | |
| if ! command -v 'xxd' &>/dev/null; then | |
| printf '%s\n' "Missing required application: 'xxd'" >&2 | |
| return 1 | |
| fi | |
| xxd --revert --plain "${1:-/dev/stdin}" | |
| } | |
| #Or, if you have a live stream's full URL (use with Twitch, YouTube, | |
| #etc.)... Usage: stream https://examplestreamservice.tv/user | |
| stream() { | |
| local i | |
| if [[ -z "${1}" || "${1}" =~ -(h|-help) ]]; then | |
| printf '%s\n' "USAGE: ${FUNCNAME[0]} [-h|--help] URL" | |
| return 0 | |
| fi | |
| for i in 'mpv' 'yt-dlp'; do | |
| command -v "${i}" &>/dev/null && continue | |
| printf '%s\n' "Missing required application: '${i}'" >&2 | |
| return 1 | |
| done | |
| mpv "${1}" | |
| } | |
| #Play Twitch streams with MPV in GUI or TTY | |
| # | |
| # Usage: twitch username | |
| # You may have to add "1080p" to the function if for whatever | |
| # reason the stream does not have a 720p or lower option; keeping | |
| # it low helps on older/lighter hardware. | |
| # Use 'sudo pip install streamlink' to install 'streamlink'. | |
| # | |
| twitch() { | |
| if [[ -z "${1}" || "${1}" =~ -(h|-help) ]]; then | |
| printf '%s\n' "USAGE: ${FUNCNAME[0]} [-h|--help] CHANNEL" | |
| return 0 | |
| fi | |
| stream "https://twitch.tv/${1}" | |
| } | |
| #Play just about anything web related that youtube-dl supports | |
| #You can also replace 'youtube-dl' with 'yt-dlp' | |
| webplay() { | |
| if [[ -z "${1}" || "${1}" =~ -(h|-help) ]]; then | |
| printf '%s\n' "USAGE: ${FUNCNAME[0]} [-h|--help] URL" | |
| return 0 | |
| fi | |
| if ! command -v "mpv" &>/dev/null; then | |
| printf '%s\n' "Missing required application: 'mpv'" >&2 | |
| return 1 | |
| fi | |
| mpv "${1}" | |
| } | |
| webplayer() { | |
| webplay "${@}" | |
| } | |
| # Get last viewed/attempted video from Kodi logfile | |
| get_last_kodi() { | |
| awk ' | |
| /mp4/ { | |
| video = gensub(/^([^\|]+?).*$/, "\\1", 1, $0) | |
| } | |
| END { | |
| print video | |
| } | |
| ' "${HOME}/.kodi/temp/kodi.log" | |
| } | |
| #Play last viewed, or attempted to view video from Kodi using mpv; may | |
| #not work due to CDNs (Content Delivery Networks). | |
| mpvkodi() { | |
| if [[ -n "${1}" ]]; then | |
| printf '%s\n' "USAGE: ${FUNCNAME[0]} [-h|--help]" | |
| return 0 | |
| fi | |
| if ! command -v 'mpv' &>/dev/null; then | |
| printf '%s\n' "Missing required application: 'mpv'" >&2 | |
| return 1 | |
| fi | |
| mpv "$(get_last_kodi)" | |
| } | |
| #If playback on Kodi is slow, download last viewed, or attempted to view | |
| #video using axel; may not work do to CDNs (Content Delivery Networks). | |
| axelkodi() { | |
| if [[ -n "${1}" ]]; then | |
| printf '%s\n' "USAGE: ${FUNCNAME[0]} [-h|--help]" | |
| return 0 | |
| fi | |
| if ! command -v 'kodi' &>/dev/null; then | |
| printf '%s\n' "Missing required application: 'kodi'" >&2 | |
| return 1 | |
| fi | |
| axel --num-connections="10" "$(get_last_kodi)" | |
| } | |
| #Do a fuzzy search using 'fzy' for an installed program in the | |
| #"/usr/share/applications/" and "$HOME/.local/share/applications" | |
| #directories and run it; you can replace the 'fzy' with 'fzf' if it is | |
| #installed. Also, you may have to replace 'xdg-open' with 'exo-open'. | |
| #If nothing is selected and 'CTRL+C' is used to exit, 'xdg-open' and | |
| #'exo-open' will print the --help; it is what it is. | |
| appsearch() { | |
| local i | |
| if [[ -n "${1}" ]]; then | |
| printf '%s\n' "USAGE: ${FUNCNAME[0]} [-h|--help]" | |
| return 0 | |
| fi | |
| for i in 'fzy' 'xdg-open'; do | |
| command -v "${i}" &>/dev/null && continue | |
| printf '%s\n' "Missing required application: '${i}'" >&2 | |
| return 1 | |
| done | |
| find "/usr/share/applications" "${XDG_DATA_HOME:-${HOME}/.local/share}/applications" -type f 2>/dev/null | \ | |
| fzy | \ | |
| xargs -I {} xdg-open "{}" | |
| } | |
| run() { | |
| appsearch "${@}" | |
| } | |
| #Use curl and "https://cht.sh/" to quickly search how to do things | |
| #Examples: 'howin html do I view an image' | |
| # 'howin python do I add numbers' | |
| howin() { | |
| if [[ -z "${1}" || "${1}" =~ -(h|-help) ]]; then | |
| printf '%s\n' "USAGE: ${FUNCNAME[0]} LANG QUERY" | |
| return 0 | |
| fi | |
| local lang | |
| lang="${1}" | |
| shift | |
| curl "https://cheat.sh/${lang}/${*}" | |
| } | |
| #Create comma-separated, single-quoted, lists from multi-line output | |
| # Usage example: cat '/path/to/multi-lineList.txt' | commalist | |
| function commalist() { | |
| if [[ "${1}" =~ -(h|-help) ]]; then | |
| printf '%s\n' "USAGE: ${FUNCNAME[0]} [-h|--help] [FILE [...]]" | |
| return 0 | |
| fi | |
| sed "s/^/'/;s/$/'/" "${@:-/dev/stdin}" | \ | |
| paste --serial --delimiter="," | \ | |
| sed 's/,/, /g' | |
| } | |
| #Use the following functions to create an encrypted PDF from all of the | |
| #the images in the current directory. Start with 'img2pdfenc' and if | |
| #you get an "Invalid" error, use the 'img2pdfcheck' function to go | |
| #through each image and print the file-names associated with the error | |
| #as 'img2pdf' annoying does not do this for you; echo "$i" helps; the | |
| #'img2pdfcheck' function will take a long time if you have a lot of | |
| #images; it uses a FOR-LOOP, so it does not check recursively. If you | |
| #already have a PDF you want to encrypt, run the 'pdf2enc' function. | |
| # | |
| # Usage Example: img2pdfenc output.pdf | |
| # Usage Example: pdf2enc input.pdf output.pdf | |
| # Usage Example: pdf2decrypt input.pdf output.pdf | |
| # | |
| img2pdfenc() { | |
| local stage | |
| local -a images | |
| if [[ -z "${1}" || "${1}" =~ -(h|-help) ]]; then | |
| printf '%s\n' "USAGE: ${FUNCNAME[0]} [PDF]" | |
| return 0 | |
| fi | |
| if ! command -v 'convert' &>/dev/null; then | |
| printf '%s\n' "Missing required application: 'convert'" >&2 | |
| return 1 | |
| fi | |
| mapfile -t images < <(find "${PWD}" -type f -iname "*.jpg" -printf '%p\n' 2>/dev/null) | |
| if (( ${#images} == 0 )); then | |
| printf '%s\n' "No jpegs in current path" >&2 | |
| return 1 | |
| fi | |
| stage="$(mktemp --tmpdir="/tmp" "tmp.XXXXXXXXXXXX.pdf")" | |
| if ! convert "${images[@]}" "${stage}"; then | |
| printf '%s\n' "Failed to merge images into PDF: './*.jpg' !> '${stage}'" >&2 | |
| rm --force "${stage}" | |
| return 1 | |
| fi | |
| if ! pdf2enc "${stage}" "${1:-${PWD}/${PWD##*/}.enc.pdf}"; then | |
| printf '%s\n' "Failed to created encrypted PDF: '${_}'" >&2 | |
| rm --force "${stage}" | |
| return 1 | |
| fi | |
| rm --force "${stage}" | |
| return 0 | |
| } | |
| pdf2enc() { | |
| if [[ -z "${1}" || "${1}" =~ -(h|-help) ]]; then | |
| printf '%s\n' "USAGE: ${FUNCNAME[0]} INPUT OUTPUT" | |
| return 0 | |
| fi | |
| if ! command -v 'pdftk' &>/dev/null; then | |
| printf '%s\n' "Missing required application: 'pdftk'" >&2 | |
| return 1 | |
| fi | |
| pdftk "${1}" output "${2}" user_pw PROMPT | |
| } | |
| pdf2decrypt() { | |
| if [[ -z "${1}" || "${1}" =~ -(h|-help) ]]; then | |
| printf '%s\n' "USAGE: ${FUNCNAME[0]} INPUT OUTPUT" | |
| return 0 | |
| fi | |
| if ! command -v 'pdftk' &>/dev/null; then | |
| printf '%s\n' "Missing required application: 'pdftk'" >&2 | |
| return 1 | |
| fi | |
| pdftk "${1}" input_pw PROMPT output "${2}" | |
| } | |
| #Potentially lower an animated GIF's (89a) file size using gifsicle | |
| # | |
| # Usage: optgif input.gif output.gif | |
| # | |
| function optgif() { | |
| if [[ -z "${1}" || "${1}" =~ -(h|-help) ]]; then | |
| printf '%s\n' "USAGE: ${FUNCNAME[0]} [-h|--help] INPUT [OUTPUT]" | |
| return 0 | |
| fi | |
| if ! command -v 'gifsicle' &>/dev/null; then | |
| printf '%s\n' "Missing required application: 'gifsicle'" >&2 | |
| return 1 | |
| fi | |
| gifsicle \ | |
| --interlace "${1}" \ | |
| --optimize="3" \ | |
| --output "${2:-${1%.*}.optimized.gif}" | |
| } | |
| #Displaying a #hex or rgb(#,#,#) color using ImageMagick; this is so you | |
| #do not have to do an Internet search or open a heavy program just to | |
| #find out what the color looks like. Do not forget the quotes. | |
| # | |
| # Usage HEX: dispcolor '#hex' | |
| # Usage RGB: dispcolor 'rgb(#,#,#)' | |
| # | |
| displaycolor() { | |
| if [[ -z "${1}" || "${1}" =~ -(h|-help) ]]; then | |
| printf "USAGE: ${FUNCNAME[0]} [-h|--help] %s\n" '#RRGGBB' 'rgb(R,G,B)' | |
| return 0 | |
| fi | |
| if ! command -v 'display' &>/dev/null; then | |
| printf '%s\n' "Missing required application: 'display'" >&2 | |
| return 1 | |
| fi | |
| display -size '300x300' "xc:${1}" | |
| } | |
| dispcolor() { | |
| displaycolor "${@}" | |
| } | |
| #If you are encrypting/decrypting files using OpenSSL... | |
| # | |
| # Usage encrypt: encrypt normalFile.ext encryptedFile.enc public.key | |
| # Usage decrypt: decrypt encryptedFile.enc private.key | |
| # | |
| encrypt() { | |
| if [[ -z "${1}" || "${1}" =~ -(h|-help) ]]; then | |
| printf '%s\n' "USAGE: ${FUNCNAME[0]} [-h|--help] INFILE OUTFILE PUBKEY" | |
| return 0 | |
| elif ! [[ -s "${1}" ]]; then | |
| printf '%s\n' "Input file is empty or does not exist: '${1}'" >&2 | |
| return 1 | |
| fi | |
| if ! command -v 'openssl' &>/dev/null; then | |
| printf '%s\n' "Missing required application: 'openssl'" >&2 | |
| return 1 | |
| fi | |
| openssl smime \ | |
| -encrypt \ | |
| -binary \ | |
| -aes-256-cbc \ | |
| -in "${1}" \ | |
| -out "${2}" \ | |
| -outform "DEM" \ | |
| "${3}" | |
| } | |
| decrypt() { | |
| if [[ -z "${1}" || "${1}" =~ -(h|-help) ]]; then | |
| printf '%s\n' "USAGE: ${FUNCNAME[0]} [-h|--help] FILE PRIVKEY" | |
| return 0 | |
| elif ! [[ -s "${1}" ]]; then | |
| printf '%s\n' "Input file is empty or does not exist: '${1}'" >&2 | |
| return 1 | |
| fi | |
| if ! command -v 'openssl' &>/dev/null; then | |
| printf '%s\n' "Missing required application: 'openssl'" >&2 | |
| return 1 | |
| fi | |
| openssl smime \ | |
| -decrypt \ | |
| -in "${1}" \ | |
| -binary \ | |
| -inform "DEM" \ | |
| -inkey "${2}" | |
| } | |
| #Sorts out unique lines | |
| # | |
| # Usage: unique '/path/to/file.txt' | |
| # | |
| unique() { | |
| awk '!seen[$0]++' | |
| } | |
| #Grab a copy of an entire website or starting from whichever URL you use | |
| #in place of "$1". It doesn't always work 100% of the time and do not | |
| #get made at me if a server bands you for using it. | |
| # | |
| # Usage: grabindex https://example.org | |
| # | |
| grabindex() { | |
| if [[ -z "${1}" || "${1}" =~ -(h|-help) ]]; then | |
| printf '%s\n' "USAGE: ${FUNCNAME[0]} URL [OUTDIR]" | |
| return 0 | |
| fi | |
| if ! command -v 'wget' &>/dev/null; then | |
| printf '%s\n' "missing required application: 'wget'" >&2 | |
| return 1 | |
| fi | |
| [[ -n "${2}" ]] && mkdir --parents "${2}" | |
| wget \ | |
| --mirror \ | |
| --convert-links \ | |
| --no-verbose \ | |
| --no-host-directories \ | |
| --no-clobber \ | |
| --page-requisites \ | |
| --html-extension \ | |
| --no-parent \ | |
| --reject-regex '\?' \ | |
| --restrict-file-names="windows" \ | |
| --execute "robots=off" \ | |
| --directory-prefix="${2:-${PWD}}" | |
| "${@}" | |
| } | |
| #Use 'axel' download accelorator with youtube-dl to grab YouTube videos | |
| # | |
| # Usage: axelyt https://youtube.com/watch?v=??????????? | |
| # | |
| #HOWEVER, instead, you may want to consider using 'yt-dlp' | |
| # | |
| axelyt() { | |
| local i | |
| if [[ -z "${1}" || "${1}" =~ -(h|-help) ]]; then | |
| printf '%s\n' "USAGE: ${FUNCNAME[0]} [-h|--help] VIDEOID" | |
| return 0 | |
| fi | |
| for i in 'yt-dlp' 'axel'; do | |
| command -v "${i}" &>/dev/null && continue | |
| printf '%s\n' "Missing required application: '${i}'" >&2 | |
| return 1 | |
| done | |
| yt-dlp \ | |
| --continue \ | |
| --ignore-errors \ | |
| --user-agent "Mozilla" \ | |
| --downloader "axel" \ | |
| --downloader-args "axel:--num-connections 10" \ | |
| "${1}" | |
| } | |
| #Lists URLs that start with 'http' or 'https' on a webpage using lynx | |
| # | |
| # Usage: listurls https://example.org | |
| # | |
| listurls() { | |
| if [[ -z "${1}" || "${1}" =~ -(h|-help) ]]; then | |
| printf '%s\n' "USAGE: ${FUNCNAME[0]} [-h|--help] URL" | |
| return 0 | |
| fi | |
| if ! command -v 'lynx' &>/dev/null; then | |
| printf '%s\n' "Missing required application: 'lynx'" >&2 | |
| return 1 | |
| fi | |
| lynx -dump -listonly -image_links -nonumbers "${@}" | \ | |
| sed --quiet '/http/p' | |
| } | |
| #Download "nicely embedded" images from a site page; this function does | |
| #not work if lynx gives JS errors. Or, you can use 'gallery-dl' via | |
| #'sudo pip install gallery-dl' for more complex sites. | |
| # | |
| # Usage: grabimg https://example.org | |
| # | |
| grabimg() { | |
| local i | |
| if [[ -z "${1}" || "${1}" =~ -(h|-help) ]]; then | |
| printf '%s\n' "USAGE: ${FUNCNAME[0]} [-h|--help] URL" | |
| return 0 | |
| fi | |
| for i in 'lynx' 'wget'; do | |
| command -v "${i}" &>/dev/null && continue | |
| printf '%s\n' "Missing required application: '${i}'" >&2 | |
| return 1 | |
| done | |
| # based on: https://stackoverflow.com/a/71550235 | |
| lisurls "${@}" | \ | |
| awk --assign "ORS=\000" '/\.(jpg|png)$/' | |
| xargs -0 wget --no-verbose | |
| } | |
| #Use this as a way to get nano to create a text file that is a bit more | |
| #DOS-friendly. Make sure your file name has no spaces and is only 8 | |
| #characters long and does not have more than 3 characters for the file- | |
| #extension. | |
| # | |
| # Usage doswrite /path/to/new/file.txt | |
| # | |
| doswrite() { | |
| local fname ext | |
| if [[ -z "${1}" || "${1}" =~ -(h|-help) ]]; then | |
| printf '%s\n' "USAGE: ${FUNCNAME[0]} [-h|--help] FILE" | |
| return 0 | |
| fi | |
| if ! command -v 'nano' &>/dev/null; then | |
| printf '%s\n' "Missing required application: 'nano'" >&2 | |
| return 1 | |
| fi | |
| fname="$(basename "${1%%.*}")" | |
| ext="${1##*.}" | |
| if (( ${#fname} > 8 )); then | |
| printf '%s\n' "Filename must be 8 characters or less: '${1##*/}'" >&2 | |
| return 1 | |
| fi | |
| if (( ${#ext} > 3 )); then | |
| printf '%s\n' "Extension must be 3 characters or less: '${1##*/}'" >&2 | |
| return 1 | |
| fi | |
| nano \ | |
| --mouse \ | |
| --unix \ | |
| --constantshow \ | |
| --breaklonglines \ | |
| --linenumbers \ | |
| --tabsize="4" \ | |
| --fill="72" \ | |
| --atblanks \ | |
| --autoindent \ | |
| "${1}" || return | |
| sed -i'' 's/\n/\r\n/' "${1}" | |
| } | |
| #Mount a raw image (IMG) file containing an installation of FreeDOS | |
| # | |
| # Usage: fdsomount '/path/to/fdos.img' '/path/to/mount/point' | |
| # | |
| dosmount() { | |
| if [[ -z "${1}" || "${1}" =~ -(h|-help) ]]; then | |
| printf '%s\n' "USAGE: ${FUNCNAME[0]} [-h|--help] IMG MOUNT" | |
| return 0 | |
| elif ! [[ -s "${1}" ]]; then | |
| printf '%s\n' "Image file is empty or does not exist: '${1}'" >&2 | |
| return 1 | |
| fi | |
| if [[ -z "${2}" ]]; then | |
| printf '%s\n' "No mount point specified" >&2 | |
| return 1 | |
| fi | |
| sudo mkdir --parents "${2}" | |
| sudo mount --options "loop,offset=32256" "${@}" | |
| } | |
| #Look for files within current directory and all sub directories that | |
| #were modified between two dates | |
| # | |
| # Usage: cd /path/to/directory && findbetween yesterday | |
| # Usage: cd /path/to/directory && findbetween "2 weeks ago" "1 week ago" | |
| # | |
| findbetween() { | |
| if [[ -z "${1}" || "${1}" =~ -(h|-help) ]]; then | |
| printf '%s\n' "USAGE: ${FUNCNAME[0]} [-h|--help] DATE1 [DATE2]" | |
| return 0 | |
| fi | |
| find "${PWD}" \ | |
| -type f \ | |
| -newermt "$(date --date="${1}" --iso-8601)" \ | |
| ! -newermt "$(date --date="${2:-today}" --iso-8601)" | |
| } | |
| #Convert an image to a 10 second MP4 video | |
| # | |
| # Usage: img2vid 'input.jpg' 640 480 'output.mp4' | |
| # | |
| #The numbers above are for WxH in pixels | |
| img2vid() { | |
| if [[ -z "${1}" || "${1}" =~ -(h|-help) ]]; then | |
| printf '%s\n' "USAGE: ${FUNCNAME[0]} [-h|--help] IMG X Y [MP4]" | |
| return 0 | |
| elif ! [[ -s "${1}" ]]; then | |
| printf '%s\n' "Image file is empty or does not exist: '${1}'" >&2 | |
| return 1 | |
| elif ! file --mime "${1}" | grep --quiet "image"; then | |
| printf '%s\n' "File is not an image: '${1}'" >&2 | |
| return 1 | |
| fi | |
| if [[ -z "${2}" ]]; then | |
| printf '%s\n' "Must include a X value for scaling" >&2 | |
| return 1 | |
| elif [[ "${2}" =~ [^0-9.\-] ]]; then | |
| printf '%s\n' "X value contains invalid characters: '${2}'" >&2 | |
| return 1 | |
| fi | |
| if [[ -z "${3}" ]]; then | |
| printf '%s\n' "Must include a Y value for scaling" >&2 | |
| return 1 | |
| elif [[ "${3}" =~ [^0-9.\-] ]]; then | |
| printf '%s\n' "Y value contains invalid characters: '${3}'" >&2 | |
| return 1 | |
| fi | |
| if ! command -v 'ffmpeg' &>/dev/null; then | |
| printf '%s\n' "Missing required application: 'ffmpeg'" >&2 | |
| return 1 | |
| fi | |
| ffmpeg \ | |
| -hide_banner \ | |
| -threads "0" \ | |
| -loop "1" \ | |
| -i "${1}" \ | |
| -c:v 'libx264' \ | |
| -t 10 \ | |
| -pix_fmt 'yuv420p' \ | |
| -vf "scale=${2}:${3}" \ | |
| "${4:-${1%.*}.mp4}" | |
| } | |
| #Merge video and audio together; replaces current audio if it exists | |
| # | |
| # Usage: avmerge 'video.ext' 'audio.ext' [output.ext] | |
| # | |
| function avmerge() { | |
| if [[ -z "${1}" || "${1}" =~ -(h|-help) ]]; then | |
| printf '%s\n' "USAGE: ${FUNCNAME[0]} VIDEO AUDIO [OUTFILE]" | |
| return 0 | |
| elif ! [[ -s "${1}" ]]; then | |
| printf '%s\n' "Video file is empty or does not exist: '${1}'" >&2 | |
| return 1 | |
| fi | |
| if [[ -z "${2}" ]]; then | |
| printf '%s\n' "No audio file specified" >&2 | |
| return 1 | |
| elif ! [[ -s "${2}" ]]; then | |
| printf '%s\n' "Audio file is empty or does not exist: '${2}'" >&2 | |
| return 1 | |
| fi | |
| if ! command -v 'ffmpeg' &>/dev/null; then | |
| printf '%s\n' "Missing required application: 'ffmpeg'" >&2 | |
| return 1 | |
| fi | |
| ffmpeg \ | |
| -hide_banner \ | |
| -threads "0" \ | |
| -i "${1}" \ | |
| -i "${2}" \ | |
| -map "0:v" \ | |
| -map "1:a" \ | |
| -c:v "copy" \ | |
| -shortest \ | |
| "${3:-${1%/*}/$(date '+%F-%H-%M-%S').mp4}" | |
| } | |
| #Add an image (album cover) to an MP3 using ffmpeg | |
| # | |
| # Usage: addimage '/path/to/image.jpg' '/path/to/audio.mp3' | |
| # | |
| addimage() { | |
| local stage | |
| if [[ -z "${1}" || "${1}" =~ -(h|-help) ]]; then | |
| printf '%s\n' "USAGE: ${FUNCNAME[0]} IMAGE MP3" | |
| return 0 | |
| elif ! [[ -s "${1}" ]]; then | |
| printf '%s\n' "Image file is empty or does not exist: '${1}'" >&2 | |
| return 1 | |
| elif ! file --mime "${1}" | grep --quiet "image"; then | |
| printf '%s\n' "Image file is not an image: '${1}'" >&2 | |
| return 1 | |
| fi | |
| if [[ -z "${2}" ]]; then | |
| printf '%s\n' "No MP3 file specified" >&2 | |
| return 1 | |
| elif ! file --mime "${2}" | grep --quiet 'audio/mpeg'; then | |
| printf '%s\n' "Audio file is not an MP3: '${2}'" >&2 | |
| return 1 | |
| fi | |
| if ! command -v 'ffmpeg' &>/dev/null; then | |
| printf '%s\n' "Missing required application: 'ffmpeg'" >&2 | |
| return 1 | |
| fi | |
| stage="$(mktempt --tmpdir="/tmp" "tmp.XXXXXXXXXXX.mp3")" | |
| ffmpeg \ | |
| -i "${2}" \ | |
| -i "${1}" \ | |
| -map "0:0" \ | |
| -map "1:0" \ | |
| -c "copy" \ | |
| -id3v2_version "3" \ | |
| -metadata:s:v "title=Album cover" \ | |
| -metadata:s:v "comment=Cover (front)" \ | |
| "${stage}" && mv --force "${stage}" "${2}" && return 0 | |
| rm --force "${stage}" | |
| return 1 | |
| } | |
| #Copy the contents of a CD-ROM to an ISO if /dev/sr0 is your device, | |
| #to which is usually the case for external disc drives. | |
| # | |
| # Usage: cpcd output.iso | |
| # | |
| cpcd() { | |
| local dev bs i | |
| if [[ -z "${1}" || "${1}" =~ -(h|-help) ]]; then | |
| printf '%s\n' "USAGE: ${FUNCNAME[0]} [-h|--help] ISO" | |
| return 0 | |
| fi | |
| dev="$(blkid | sed --quiet '/iso9660' | sed '1q')" | |
| if [[ -z "${dev}" ]]; then | |
| printf '%s\n' "Cannot locate CD-ROM" >&2 | |
| return 1 | |
| fi | |
| dev="${dev%%:*}" | |
| for i in "isoinfo" "isosize"; do | |
| command -v "${i}" &>/dev/null && continue | |
| printf '%s\n' "Missing required application: '${i}'" >&2 | |
| return 1 | |
| done | |
| isinfo -di "${dev}" || return | |
| bs="2048" | |
| dd \ | |
| if="${dev}" \ | |
| of="${1}" \ | |
| bs="${bs}" \ | |
| count="$(isosize -d "${bs}" "${dev}" 2>/dev/null)" \ | |
| status="progress" | |
| } | |
| #Move up by a number of specified directories | |
| function up(){ | |
| local i path | |
| if [[ -z "${1}" || "${1}" =~ -(h|-help) ]]; then | |
| printf '%s\n' "USAGE: ${FUNCNAME[0]} [-h|--help] NUM" | |
| return 0 | |
| elif [[ "${1}" =~ [^0-9] ]]; then | |
| printf '%s\n' "Invalid number format: '${1}'" >&2 | |
| return 1 | |
| fi | |
| for (( i = 0; i < ${1}; i++ )); do | |
| path+="../" | |
| done | |
| cd "$(realpath "${path:-${PWD}}")" || return | |
| } | |
| #Create an empty audio file for n amount of seconds. | |
| #This is useful for DVD authoring software (DevedeNG, DVD Styler, etc.) | |
| #in which you need an audio layer for menus, even if it is an empty one; | |
| #some older DVD players and game consoles notice when this is missing | |
| #and may create a short (or long) "chirp" noise during certain menus, | |
| #especially those with background video or animated chapter selection. | |
| #Sometimes these menus are loopable but only loop based on whether the | |
| #video layer or audio layer, if separate, have the smallest amount of | |
| #time. Hopefully this makes sense. | |
| # | |
| #Usage: emptyaudio seconds output.mp3 | |
| # | |
| emptyaudio() { | |
| if [[ -z "${1}" || "${1}" =~ -(h|-help) ]]; then | |
| printf '%s\n' "USAGE: ${FUNCNAME[0]} [-h|--help] LENGTH MP3" | |
| return 0 | |
| elif [[ "${1}" =~ [^0-9\.] ]]; then | |
| printf '%s\n' "Invalid length: '${1}'" >&2 | |
| return 1 | |
| elif [[ -z "${2}" ]]; then | |
| printf '%s\n' "No MP3 file specified" >&2 | |
| return 1 | |
| fi | |
| if ! command -v 'ffmpeg' &>/dev/null; then | |
| printf '%s\n' "Missing required application: 'ffmpeg'" >&2 | |
| return 1 | |
| fi | |
| ffmpeg \ | |
| -hide_banner \ | |
| -threads "0" \ | |
| -ar "48000" \ | |
| -t "${1}" \ | |
| -f "s16le" \ | |
| -i "/dev/zero" \ | |
| "${2}" | |
| } | |
| #This function lists the most used commands and how many times in a simplistic way | |
| top-history() { | |
| tr '|' "\n" < "${HOME}/.bash_history" | \ | |
| awk ' | |
| { | |
| seen[$1]++ | |
| } | |
| END { | |
| for (i in seen) | |
| print seen[i] " " i | |
| } | |
| ' | \ | |
| sort --numeric-sort --reverse | \ | |
| head -10 | \ | |
| column -t | |
| } | |
| #Convert a video to a bunch of JPEG's | |
| # | |
| # Usage example: video2jpg /path/to/video.mp4 [framerate] | |
| # | |
| video2jpg() { | |
| if [[ -z "${1}" || "${1}" =~ -(h|-help) ]]; then | |
| printf '%s\n' "USAGE: ${FUNCNAME[0]} [-h|--help] MP4 FPS [OUTDIR]" | |
| return 0 | |
| elif ! [[ -s "${1}" ]]; then | |
| printf '%s\n' "Input file is empty or does not exist: '${1}'" >&2 | |
| return 1 | |
| elif ! file --mime "${1}" | grep --quiet 'video/mp4'; then | |
| printf '%s\n' "Input file is not an MP4: '${1}'" >&2 | |
| return 1 | |
| elif [[ -z "${2}" ]]; then | |
| printf '%s\n' "No framerate specified" >&2 | |
| return 1 | |
| elif [[ "${2}" =~ [^0-9.] ]]; then | |
| printf '%s\n' "Invalid FPS Amount: '${2}'" >&2 | |
| return 1 | |
| fi | |
| if ! command -v 'ffmpeg' &>/dev/null; then | |
| printf '%s\n' "Missing required application: 'ffmpeg'" >&2 | |
| return 1 | |
| fi | |
| ffmpeg \ | |
| -hide_banner \ | |
| -threads "0" \ | |
| -i "${1}" \ | |
| -r "${2}" \ | |
| "${3:-${1%/*}}/$(basename "${1%.*}")_%05d.jpg" | |
| } | |
| #Use this to send random numbers to the clipboard every five seconds; it | |
| #is very useful if selectively saving a bunch of long-named files from a | |
| #website but could care less about the name of the files. Just use | |
| #CTRL+v like usual in the SAVE-AS area of the file-saving dialog to | |
| #paste the number. I guess it could also help with those paranoid about | |
| #certain software having clipboard access, though I have no idea why | |
| #anyone would voluntarily run that sort of thing. | |
| randomclip() { | |
| local -a clip | |
| clip=('xsel' '--clipboard') | |
| if uname --kernel-release | grep --quiet "microsoft.*WSL"; then | |
| clip=('clip.exe') | |
| elif [[ "${XDG_SESSION_TYPE,,}" != "x11" ]]; then | |
| clip=('wl-copy') | |
| fi | |
| if ! command -v "${clip[0]}" &>/dev/null; then | |
| printf '%s\n' "Cannot locate clipboard command: '${clip[0]}'" >&2 | |
| return 1 | |
| fi | |
| while true; do | |
| "${clip[@]}" <<< "${RANDOM}" | |
| sleep 5 | |
| done | |
| } | |
| #Need a simple espeak timer? Values can be things like 10s, 30m, 1h. | |
| #However, because of how simplistic this is, you cannot combine times so | |
| #if you need something like "1h 30m," then you need to use "90m" | |
| #instead, without the quotes. The second argument will need quotes. | |
| # | |
| # Example: espeaktimer 30m "Go check your oven!" | |
| # | |
| espeaktimer() { | |
| local i | |
| if [[ -z "${1}" || "${1}" =~ -(h|-help) ]]; then | |
| printf '%s\n' "USAGE: ${FUNCNAME[0]} TIME TEXT" | |
| return 0 | |
| fi | |
| for i in 'at' 'espeak'; do | |
| command -v "${i}" &>/dev/null && continue | |
| printf '%s\n' "Missing required application: '${i}'" >&2 | |
| return 1 | |
| done | |
| at "${1}" <<< "espeak '${2}'" | |
| } | |
| #I did not like how the 'ebook-convert' program from 'Calibre' converts | |
| #comic books to whatever with automatic grayscale, especially when the | |
| #CBR or CBZ file in question is not a typical comic and is full-color. | |
| # | |
| # Usage: ebook-convert-cbz input.cb[r,z] output.ext | |
| # | |
| ebook_convert_cbz() { | |
| if [[ -z "${1}" || "${1}" =~ -(h|-help) ]]; then | |
| printf "USAGE: ${FUNCNAME[0]} %s OUTFILE\n" "CBR" "CBZ" | |
| return 0 | |
| elif ! [[ -s "${1}" ]]; then | |
| printf '%s\n' "Input file is empty or does not exist: '${1}'" >&2 | |
| return 1 | |
| elif [[ -z "${2}" ]]; then | |
| printf '%s\n' "No output file specified" >&2 | |
| return 1 | |
| fi | |
| if ! command -v 'ebook-convert' &>/dev/null; then | |
| printf '%s\n' "Missing required application: 'ebook-convert'" >&2 | |
| return 1 | |
| fi | |
| ebook-convert \ | |
| "${1}" \ | |
| "${2}" \ | |
| --dont-grayscale \ | |
| --dont-normalize \ | |
| --no-process | |
| } |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| #!/usr/bin/env bash | |
| export PATH="${PATH}:${HOME}/scripts" | |
| # Add color in manpages for less | |
| export LESS_TERMCAP_mb=$'\E[01;31m' | |
| export LESS_TERMCAP_md=$'\E[01;31m' | |
| export LESS_TERMCAP_me=$'\E[0m' | |
| export LESS_TERMCAP_se=$'\E[0m' | |
| export LESS_TERMCAP_so=$'\E[01;44;33m' | |
| export LESS_TERMCAP_ue=$'\E[0m' | |
| export LESS_TERMCAP_us=$'\E[01;32m' | |
| # Colors for all grep commands such as grep, egrep and zgrep | |
| export GREP_OPTIONS='--color=auto' | |
| # Tasklist prompt, sorta | |
| bashtask.sh --init &>/dev/null | |
| bashtask.sh --print | |
| [[ -s "${HOME}/.bash_functions" ]] && source "${HOME}/.bash_functions" | |
| [[ -s "${HOME}/.bash_aliases" ]] && source "${HOME}/.bash_aliases" |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| #!/usr/bin/env bash | |
| # | |
| # Simple todo-list | |
| show_help() { | |
| cat << EOF | |
| Simple todo-list | |
| USAGE: ${0##*/} [OPTIONS] TASK | |
| OPTIONS: | |
| -h, --help Show this help message | |
| -a, --add Add TASK to end of the list (default) | |
| -i, --insert POS Insert TASK at line POS | |
| -r, --remove POS Remove TASK at line POS | |
| -x, --clear Remove all tasks in list | |
| -p, --print Show all tasks | |
| --init Initialize tasklist and exit | |
| ENVIRONMENT: | |
| The BASHTASK_FILE variable can be set to specify a custom location of the | |
| tasklist. By default '\$XDG_CONFIG_HOME/bashtask/list' | |
| EOF | |
| } | |
| _header() { | |
| local red blue nc | |
| red="$(tput setaf 1)" | |
| blue="$(tput setaf 4)" | |
| nc="$(tput sgr0)" | |
| if [[ -s "${tasklist}" ]]; then | |
| printf '%s\n\n' "${red}Task List${nc} as of ${blue}$(date --referece="${tasklist}")${nc}" | |
| print_list | |
| else | |
| printf '%s\n' "Yay! No tasks :)" | |
| fi | |
| printf '%80s\n' " " | tr ' ' "-" | |
| } | |
| print_list() { | |
| sed 's/^/- /' "${tasklist}" | |
| } | |
| main() { | |
| local opts tasklist action position | |
| opts="$(getopt \ | |
| --options haxpi:r: \ | |
| --longoptions "help,add,clear,print,insert:,remove:,init" \ | |
| --name "${0##*/}" \ | |
| -- "${@}" \ | |
| )" | |
| action="add" | |
| tasklist="${XDG_CONFIG_HOME:-${HOME}/.config}/bashtask/list" | |
| tasklist="${BASHTASK_FILE:-${tasklist}}" | |
| eval set -- "${opts}" | |
| while true; do | |
| case "${1}" in | |
| -h | --help ) show_help; return 0;; | |
| -a | --add ) action="add";; | |
| -i | --insert ) action="ins"; position="${2}"; shift;; | |
| -r | --remove ) action="del"; position="${2}"; shift;; | |
| -x | --clear ) action="cls";; | |
| -p | --print ) action="cat";; | |
| --init ) action="init";; | |
| -- ) shift; break;; | |
| * ) break;; | |
| esac | |
| shift | |
| done | |
| mkdir --parents "${tasklist%/*}" | |
| touch -a "${tasklist}" | |
| [[ "${action}" == "init" ]] && return 0 | |
| if [[ "${action}" =~ (add|ins) && -z "${1}" ]]; then | |
| printf '%s\n' "Task not specified" >&2 | |
| return 1 | |
| fi | |
| case "${action}" in | |
| add ) | |
| printf '%s\n' "${1}" >> "${tasklist}" | |
| ;; | |
| ins ) | |
| if ! sed -i'' "${position}i${1}" "${tasklist}"; then | |
| printf '%s\n' "Failed to insert task" >&2 | |
| return 1 | |
| fi | |
| ;; | |
| del ) | |
| if ! sed -i'' "${position}d" "${tasklist}"; then | |
| printf '%s\n' "Failed to delete task" >&2 | |
| return 1 | |
| fi | |
| ;; | |
| cls ) | |
| touch "${tasklist}" | |
| ;; | |
| cat ) | |
| print_list | |
| ;; | |
| esac | |
| return 0 | |
| } | |
| main "${@}" |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| #!/usr/bin/env bash | |
| # | |
| # Easy way to extract archives | |
| show_help() { | |
| cat << EOF | |
| Easy way to extract archives | |
| USAGE: ${0##*/} [OPTIONS] FILE1 ... | |
| OPTIONS: | |
| -h, --help Show this help message | |
| EOF | |
| } | |
| main() { | |
| local opts err | |
| opts="$(getopt \ | |
| --options h \ | |
| --longoptions help \ | |
| --name "${0##*/}" \ | |
| -- "${@}" \ | |
| )" | |
| eval set -- "${opts}" | |
| while true; do | |
| case "${1}" in | |
| -h | --help ) show_help; return 0;; | |
| -- ) shift; break;; | |
| * ) break;; | |
| esac | |
| shift | |
| done | |
| while [[ -n "${1}" ]]; do | |
| if ! [[ -s "${1}" ]]; then | |
| printf '%s\n' "File does not exist or is empty: '${1}'" >&2 | |
| err="1" | |
| shift | |
| continue | |
| fi | |
| case "${1,,}" in | |
| *.tar* ) | |
| case "${1#*tar.}" in | |
| bz2 ) tar --extract --verbose --bzip2 --file="${1}";; | |
| tgz ) tar --extract --verbose --gzip --file="${1}";; | |
| Z ) tar --extract --verbose --compress --file="${1}";; | |
| zst ) tar --extract --verbose --zstd --file="${1}";; | |
| * ) tar --extract --verbose --file="${1}";; | |
| esac | |
| ;; | |
| *.bz2 ) | |
| bunzip2 "${1}" | |
| ;; | |
| *.rar ) | |
| unrar x "${1}" | |
| ;; | |
| *.gz ) | |
| gunzip "${1}" | |
| ;; | |
| *.zip ) | |
| unzip "${1}" | |
| ;; | |
| *.Z ) | |
| uncompress "${1}" | |
| ;; | |
| *.zst ) | |
| zstd --uncompress "${1}" | |
| ;; | |
| *.7z ) | |
| 7z x "${1}" | |
| ;; | |
| * ) | |
| printf '%s\n' "Unknown archive type: '${1}'" >&2 | |
| err="1" | |
| ;; | |
| esac | |
| shift | |
| done | |
| return "${err:-0}" | |
| } | |
| main "${@}" |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| #!/usr/bin/env bash | |
| # | |
| # Convert images using ImageMagick | |
| show_help() { | |
| cat << EOF | |
| Convert images using ImageMagick | |
| USAGE: ${0##*/} [OPTIONS] INPUT [OUTPUT] | |
| OPTIONS: | |
| -h, --help Show this help message | |
| -x, --delete Remove the source file after conversion | |
| -f, --format FMT Convert INPUT to FMT | |
| -o, --optimize Optmize INPUT's filesize | |
| FORMAT: | |
| pcx ZSoft IBM PC Paintbrush | |
| ppm Portable pixmap | |
| ilbm Amiga Interchange File Format (requires 'ppmtoilbm') | |
| jpg JPEG | |
| png PNG | |
| png8 8-bit PNG | |
| bmp Microsoft Windows Bitmap v4 | |
| bmp2 Microsoft Windows Bitmap v2 | |
| bmp3 Microsoft Windows Bitmap v3 | |
| dosbmp DOS-compliant Bitmap | |
| dosgif DOS-compliant GIF | |
| tif Tagged Image File | |
| ico Microsoft Icon | |
| gif Graphics Interchange Format | |
| EOF | |
| } | |
| require() { | |
| command -v "${1}" &>/dev/null && return | |
| printf '%s\n' "Missing required application: '${1}'" >&2 | |
| return 1 | |
| } | |
| mktemp_img() { | |
| mktemp --tempdir="/tmp" "tmp.XXXXXXXXXXXX.${1}" | |
| } | |
| get_extension() { | |
| local fmt | |
| case "${format,,}" in | |
| ilbm ) fmt="lbm";; | |
| png8 ) fmt="png";; | |
| dosbmp ) fmt="dos.bmp";; | |
| dosgif ) fmt="dos.gif";; | |
| * ) fmt="${format,,}";; | |
| esac | |
| printf '%s\n' "${fmt}" | |
| } | |
| im_conv() { | |
| local -a argv | |
| local stage | |
| case "${format,,}" in | |
| dosbmp ) | |
| argv+=("${1}" '-colors' '16' '-depth' '4' '-dither' 'none') | |
| argv+=('resize' '640x480' "BMP3:${2}") | |
| ;; | |
| dosgif ) | |
| argv+=("${1}" '-colors' '256' '-dither' 'none' '-resize' '320x200!') | |
| argv+=("GIF87:${2}") | |
| ;; | |
| gif ) | |
| argv+=("${1}" "GIF87:${2}") | |
| ;; | |
| ico ) | |
| argv+=('-background' 'transparent' "${1}") | |
| argv+=('-define' 'icon:auto-resize=16,32,48,64,128' "${2}") | |
| ;; | |
| ilbm ) | |
| require 'ppm2toilbm' || return 1 | |
| stage="$(mktemp_imp 'ppm')" | |
| convert -colors 4 -depth 2 -resize '320x200' "${1}" "${stage}" || return | |
| # Unsure what options are needed to replicate 'pictview' conversion | |
| ppm2ilbm "${stage}" > "${2}" | |
| return | |
| ;; | |
| pcx ) | |
| argv=("${1}" '-colors' '256' "${2}") | |
| ;; | |
| png8 ) | |
| stage="$(mktemp_img 'png8')" | |
| convert "${1}" "${stage}" || return | |
| mv --force "${stage}" "${2}" | |
| return | |
| ;; | |
| * ) | |
| argv+=("${1}" "${2}") | |
| ;; | |
| esac | |
| convert "${argv[@]}" | |
| } | |
| optimize() { | |
| [[ "${1#*.}" =~ i?lbm ]] && return 1 | |
| convert "${1}" \ | |
| -dither "FloydSteinberg" \ | |
| -colors "256" \ | |
| -morphology "Thicken:0.5" "3x1+0+0:1,0,0" \ | |
| -remap "netscape:" \ | |
| -ordered-dither "o8x8,6" +contrast \ | |
| "${1%%.*}_optimize_${1#*.}" | |
| } | |
| main() { | |
| local opts del format optimize | |
| opts="$(getopt \ | |
| --options hxf:o \ | |
| --longoptions help,delete,format:,optimize \ | |
| --name "${0##*/}" \ | |
| -- "${@}" \ | |
| )" | |
| eval set -- "${opts}" | |
| while true; do | |
| case "${1}" in | |
| -h | --help ) show_help; return 0;; | |
| -x | --delete ) del="1";; | |
| -f | --format ) format="${2}"; shift;; | |
| -o | --optimize ) optimize="1";; | |
| -- ) shift; break;; | |
| * ) break;; | |
| esac | |
| shift | |
| done | |
| if [[ -z "${1}" ]]; then | |
| printf '%s\n' "No input file specified" >&2 | |
| return 1 | |
| elif ! [[ -s "${1}" ]]; then | |
| printf '%s\n' "Input file is empty or does not exist: '${1}'" >&2 | |
| return 1 | |
| fi | |
| require "convert" || return | |
| ( [[ "${format,,}" == "ilbm" ]] && require "ppmtoilbm" ) || return | |
| if [[ -n "${format}" ]]; then | |
| im_conv "${1}" "${2:-${1%.*}.$(get_extension)}" || return | |
| [[ -n "${optimize}" ]] && optimize "${_}" || return | |
| elif [[ -n "${optimize}" ]]; then | |
| optimize "${1}" || return | |
| else | |
| printf '%s\n' "Format/Optimize action not specified" >&2 | |
| return 1 | |
| fi | |
| [[ -n "${del}" ]] && rm --force "${1}" | |
| return 0 | |
| } | |
| main "${@}" |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| #!/usr/bin/env bash | |
| # | |
| # Independently zip each file in a given directory | |
| show_help() { | |
| cat << EOF | |
| Independently zip each file in a given directory | |
| USAGE: ${0##*/} [OPTIONS] [DIR] | |
| OPTIONS: | |
| -h, --help Show this help message | |
| -x, --delete Remove original file after successful zipping | |
| EOF | |
| } | |
| require() { | |
| command -v "${1}" &>/dev/null && return | |
| printf '%s\n' "Missing required application: '${1}'" >&2 | |
| return 1 | |
| } | |
| find_files() { | |
| find "${1}" \ | |
| -maxdepth 1 \ | |
| -type f \ | |
| ! -iname '*.zip' \ | |
| -printf '%p\n' | |
| } | |
| main() { | |
| local opts del f | |
| opts="$(getopt \ | |
| --options hx \ | |
| --longoptions help,delete \ | |
| --name "${0##*/}" \ | |
| -- "${@}" \ | |
| )" | |
| eval set -- "${opts}" | |
| while true; do | |
| case "${1}" in | |
| -h | --help ) show_help; return 0;; | |
| -x | --delete ) del="1";; | |
| -- ) shift; break;; | |
| * ) break;; | |
| esac | |
| shift | |
| done | |
| if ! [[ -d "${1:-${PWD}}" ]]; then | |
| printf '%s\n' "Cannot locate directory: '${1}'" >&2 | |
| return 1 | |
| fi | |
| require 'zip' || return 1 | |
| while read -r f; do | |
| if ! zip "${f%.*}.zip" "${f}"; then | |
| printf '%s\n' "Failed to zip file: '${f}'" >&2 | |
| continue | |
| fi | |
| [[ -n "${del}" ]] && rm --force "${f}" | |
| done < <(find_files "${1:-${PWD}}") | |
| return 0 | |
| } | |
| main "${@}" |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| #!/usr/bin/env bash | |
| # | |
| # Convert media files using ffmpeg, eyed3 & sox | |
| show_help() { | |
| cat << EOF | |
| Convert media files using ffmpeg & eyeD3 | |
| USAGE: ${0##*/} [OPTIONS] FILE [DESTINATION] | |
| OPTIONS: | |
| -h, --help Show this help message | |
| -I, --remove-images Remove all images in file | |
| -x, --delete Remove original file after conversion | |
| -8, --eight Use 8K for sample rate on supported formats (see FORMAT) | |
| -f, --format FMT Convert FILE to FMT (see FORMAT) | |
| -n, --ntsc Convert to NTSC-DVD-ready format | |
| -p, --pal Convert to PAL-DVD-ready format | |
| -s, --subtitles SRT Include subtitles SRT file in output | |
| FORMAT: | |
| ogg Vorbis/ogg | |
| wav Wave | |
| doswav DOS-compatible Wave (11K, 8K with -8) | |
| voc PlayVoc (11K, 8K with -8) | |
| opus Opus/ogg | |
| aif Audio Interchange Format | |
| mp3 MP3 | |
| mov Apple Quicktime | |
| mp4 MPEG-4 | |
| avi Audio Video Interleve | |
| webm WebM | |
| h265 H265 MPEG-4 | |
| flv Flash Video | |
| mpg MPEG | |
| gif Graphics Interchange Format | |
| EOF | |
| } | |
| require() { | |
| command -v "${1}" &>/dev/null && return 0 | |
| printf '%s\n' "Missing required application: '${1}'" >&2 | |
| return 1 | |
| } | |
| is_valid_format() { | |
| [[ "${1}" =~ (ogg|(dos)?wav|voc|opus|a(if|vi)|m(p[34g]|ov)|webm|h265|flv) ]] | |
| } | |
| get_extension() { | |
| local fmt | |
| case "${format}" in | |
| doswav ) fmt="dos.wav";; | |
| h265 ) fmt="h265.mp4";; | |
| mpg ) | |
| fmt="${format}" | |
| [[ -n "${dvd}" ]] && fmt="${dvd%-*}.${fmt}" | |
| ;; | |
| esac | |
| printf '%s\n' "${fmt:-${format}}" | |
| } | |
| remove_images() { | |
| eyeD3 --remove-all-images "${1}" | |
| } | |
| ff_conv() { | |
| local -a argv | |
| argv=('-hide_banner' '-threads' '0' '-i' "${1}") | |
| case "${format}" in | |
| ogg ) | |
| argv+=('-c:a' 'libvorbis' '-b:a' "${samplereate}") | |
| ;; | |
| doswav | voc ) | |
| argv+=('-c:a' 'pcm_u8' '-b:a' "${samplerate}" '-ac' '1') | |
| ;; | |
| opus ) | |
| argv+=('-c:a' 'libopus' '-b:a' '2K' '-vbr' 'off' '-ac' '1') | |
| ;; | |
| webm ) | |
| argv+=('-c:v' 'libvpx') | |
| ;; | |
| h265 ) | |
| argv+=('-c:v' 'libx265') | |
| ;; | |
| mpg ) | |
| if [[ -n "${dvd}" ]]; then | |
| argv+=('-i' "${1}" '-map' '1:0' '-map' '0:1' '-y') | |
| if [[ -n "${subtitles}" ]]; then | |
| argv+=('-vf' "subtitles=${subtitles// /\\ }") | |
| fi | |
| argv+=('-target' "${dvd}" '-sn' '-g' '12' '-bf' '2') | |
| argv+=('-strict' '1' '-ac' '2' '-aspect' '4/3' '-trellis' '0') | |
| argv+=('-mbd' '0' '-b:a' '224K' '-b:v' '9000K') | |
| argv+=('-passlogfile' "${2}" '-pass' '1') | |
| fi | |
| ;; | |
| gif ) | |
| argv+=('-vf' 'fps=10,scale=320:-1:flags=lanczos,split[s0][s1];[s0]palettegen[p];[s1][p]paletteuse') | |
| argv+=('-loop' '0') | |
| ;; | |
| esac | |
| ffmpeg "${argv[@]}" "${2}" | |
| } | |
| main() { | |
| local opts format rmimg samplerate del dvd subtitles | |
| opts="$(getopt \ | |
| --options hIx8f:nps: \ | |
| --longoptions help,remove-images,delete,eight,format:,ntsc,pal,subtitles: \ | |
| --name "${0##*/}" \ | |
| -- "${@}" \ | |
| )" | |
| samplerate="11K" | |
| eval set -- "${opts}" | |
| while true; do | |
| case "${1}" in | |
| -h | --help ) show_help; return 0;; | |
| -I | --remove-images ) rmimg="1";; | |
| -x | --delete ) del="1";; | |
| -8 | --eight ) samplerate="8K";; | |
| -f | --format ) format="${2}"; shift;; | |
| -n | --ntsc ) dvd="ntsc-dvd";; | |
| -p | --pal ) dvd="pal";; | |
| -s | --subtitles ) subtitles="${2}";; | |
| -- ) shift; break;; | |
| * ) break;; | |
| esac | |
| shift | |
| done | |
| require 'ffmpeg' || return 1 | |
| if [[ -z "${1}" ]]; then | |
| printf '%s\n' "No input file specified" >&2 | |
| return 1 | |
| elif ! [[ -s "${1}" ]]; then | |
| printf '%s\n' "Input file does not exist or is empty: '${1}'" >&2 | |
| return 1 | |
| fi | |
| if [[ -z "${format}" ]]; then | |
| printf '%s\n' "No format specified" >&2 | |
| return 1 | |
| elif ! is_valid_format "${format}"; then | |
| printf '%s\n' "Invalid format: '${format}'" >&2 | |
| return 1 | |
| fi | |
| if [[ -n "${subtitles}" ]]; then | |
| if ! [[ "${subtitles,,}" =~ \.srt$ ]]; then | |
| printf '%s\n' "Invalid subtitles format: '${subtitles}'" >&2 | |
| return 1 | |
| elif ! [[ -s "${subtitles}" ]]; then | |
| printf '%s\n' "Subtitles file does not exist or is empty" >&2 | |
| return 1 | |
| fi | |
| fi | |
| if [[ -n "${rmimg}" ]]; then | |
| require 'eyeD3' || return 1 | |
| printf '%s\n' "Removing album art..." | |
| remove_images "${1}" | |
| fi | |
| ff_conv "${1}" "${2:-${1%.*}.$(get_extension)}"|| return | |
| [[ -n "${del}" ]] && rm --force "${1}" | |
| } | |
| main "${@}" |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| #!/usr/bin/env bash | |
| # | |
| # Convert office documents with pandoc | |
| show_help() { | |
| cat << EOF | |
| Convert office documents with pandoc | |
| USAGE: ${0##*/} [OPTIONS] INPUT [OUTPUT] | |
| OPTIONS: | |
| -h, --help Show this help message | |
| -x, --delete Remove original file after successful operation | |
| -f, --format FMT Convert INPUT to FMT format | |
| -o, --optimize Optimize file size (PDF only) | |
| -p, --dpi DPI Set PDF's resolution to DPI (default: 96) | |
| EOF | |
| } | |
| require() { | |
| command -v "${1}" &>/dev/null && return | |
| printf '%s\n' "Missing required application: '${1}'" >&2 | |
| return 1 | |
| } | |
| optimize() { | |
| pandoc \ | |
| --standalone \ | |
| --dpi="${dpi}" \ | |
| "${1}" \ | |
| --output="${2}" | |
| } | |
| main() { | |
| local opts format optimize dpi outfile del | |
| opts="$(getopt \ | |
| --options hxf:op: \ | |
| --longoptions help,delete,format:,optimize,dpi: \ | |
| --name "${0##*/}" \ | |
| -- "${@}" \ | |
| )" | |
| dpi="96" | |
| eval set -- "${opts}" | |
| while true; do | |
| case "${1}" in | |
| -h | --help ) show_help; return 0;; | |
| -x | --delete ) del="1";; | |
| -f | --format ) format="${2}"; shift;; | |
| -o | --optimize ) optimize="1";; | |
| -p | --dpi ) dpi="${2}";; | |
| -- ) shift; break;; | |
| * ) break;; | |
| esac | |
| shift | |
| done | |
| require 'pandoc' || return 1 | |
| if [[ -z "${1}" ]]; then | |
| printf '%s\n' "No input file specified: '${1}'" >&2 | |
| return 1 | |
| elif ! [[ -s "${1}" ]]; then | |
| printf '%s\n' "Input file is empty or does not exist: '${1}'" >&2 | |
| return 1 | |
| fi | |
| outfile="${2:-${1%.*}.${format,,}}" | |
| if [[ -n "${format}" ]]; then | |
| pandoc --standalone "${1}" --output="${outfile}" || return 1 | |
| if [[ -n "${optimize}" && "${format,,}" == "pdf" ]]; then | |
| optimize "${outfile}" || return 1 | |
| fi | |
| elif [[ -n "${optimize}" && "${1%.*}" == "pdf" ]]; then | |
| optimize "${outfile%.*}.${dpi}.pdf" || return 1 | |
| else | |
| printf '%s\n' "No Conversion/Optimization action aspecified" >&2 | |
| return 1 | |
| fi | |
| [[ -n "${del}" ]] && rm --force "${1}" | |
| return 0 | |
| } | |
| main "${@}" |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| #!/usr/bin/env bash | |
| # | |
| # Set the PDF Compatability Version | |
| show_help() { | |
| cat << EOF | |
| Set the PDF Compatability Version | |
| USAGE: ${0##*/} [OPTIONS] INPUT [OUTPUT] | |
| OPTIONS: | |
| -h, --help Show this help message | |
| -x, --delete Remove the original file after successful conversion | |
| -v, --version VERSION Set the PDF compatabiliy to VERSION (default: 2.0) | |
| EOF | |
| } | |
| main() { | |
| local opts ver | |
| opts="$(getopt \ | |
| --options hxv: \ | |
| --longoptions help,delete,version: \ | |
| --name "${0##*/}" \ | |
| -- "${@}" \ | |
| )" | |
| ver="2.0" | |
| eval set -- "${opts}" | |
| while true; do | |
| case "${1}" in | |
| -h | --help ) show_help; return 0;; | |
| -x | --delete ) del="1";; | |
| -v | --version ) ver="${2}"; shift;; | |
| -- ) shift; break;; | |
| * ) break;; | |
| esac | |
| shift | |
| done | |
| if [[ -z "${1}" ]]; then | |
| printf '%s\n' "No input file specified" >&2 | |
| return 1 | |
| elif ! [[ -s "${1}" ]]; then | |
| printf '%s\n' "Input file is empty or does not exist: '${1}'" >&2 | |
| return 1 | |
| fi | |
| if ! command -v 'gs' &>/dev/null; then | |
| printf '%s\n' "Missing required application: 'gs'" >&2 | |
| return 1 | |
| fi | |
| if ! [[ "${ver}" == *.* ]]; then | |
| printf '%s\n' "Invalid PDF Version: '${ver}'" >&2 | |
| return 1 | |
| fi | |
| gs \ | |
| -dNOPAUSE \ | |
| -dBATCH \ | |
| -sDEVICE="pdfwrite" \ | |
| -dCompatibilityLevel="${ver}" \ | |
| -sOutputFile="${2:-${1%.*}.${ver//\./_}.pdf}" \ | |
| "${1}" || return | |
| [[ -n "${del}" ]] && rm --force "${1}" | |
| return 0 | |
| } | |
| main "${@}" |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| #!/usr/bin/env bash | |
| # | |
| # Quckly boot an ISO with QEMU | |
| show_help() { | |
| cat << EOF | |
| Quckly boot an ISO with QEMU | |
| USAGE: ${0##*/} [OPTIONS] ISO | |
| OPTIONS: | |
| -h, --help Show this help message | |
| -f, --file PATH Add disk-image from PATH | |
| -m, --memory MEM Specify maxmimum memory in human-readable SI units (default: 2M) | |
| -6, --i686 Boot an i586/i686 ISO | |
| -4, --i486 Boot an i486 ISO | |
| EOF | |
| } | |
| qemu_boot() { | |
| local -a argv | |
| argv=('-cdrom' "${1}" '-boot' 'd' '-m' "${mem}") | |
| [[ -n "${hda}" ]] && argv+=('-hda' "${hda}") | |
| case "${type}" in | |
| 64 ) qemu-system-x86_64 "${argv[@]}";; | |
| 686 ) qemu-system-i386 "${argv[@]}";; | |
| 486 ) qemu-system-i386 -cpu '486' "${argv[@]}";; | |
| esac | |
| } | |
| main() { | |
| local opts mem hda type i | |
| opts="$(getopt \ | |
| --options h64f:m: \ | |
| --longoptions help,i686,i486,file:,memory: \ | |
| --name "${0##*/}" \ | |
| -- "${@}" \ | |
| )" | |
| type="64" | |
| mem="2M" | |
| eval set -- "${opts}" | |
| while true; do | |
| case "${1}" in | |
| -h | --help ) show_help; return 0;; | |
| -f | --file ) hda="${2}"; shift;; | |
| -m | --memory ) mem="${2}"; shift;; | |
| -6 | --i686 ) type="686";; | |
| -4 | --i486 ) type="486";; | |
| -- ) shift; break;; | |
| * ) break;; | |
| esac | |
| shift | |
| done | |
| for i in "x86_64" "i386"; do | |
| command -v "qemu-system-${i}" &>/dev/null && continue | |
| printf '%s\n' "Missing required application: '${_}'" >&2 | |
| return 1 | |
| done | |
| if [[ -z "${1}" ]]; then | |
| printf '%s\n' "No ISO specified" >&2 | |
| return 1 | |
| elif ! [[ -s "${1}" ]]; then | |
| printf '%s\n' "ISO file is empty or does not exist: '${1}'" >&2 | |
| return 1 | |
| fi | |
| qemu_boot "${1}" | |
| } | |
| main "${@}" |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| #!/usr/bin/env bash | |
| # | |
| # Combine all of an image type in a directory into a MP4 video | |
| show_help() { | |
| cat << EOF | |
| Combine all of an image type in a directory into a MP4 video | |
| USAGE: ${0##*/} [OPTIONS] FPS [MP4] | |
| OPTIONS: | |
| -h, --help Show this help message | |
| -x, --delete Remove images after successful stitching | |
| -f, --format FMT Search for images matching FMT (default: png) | |
| -p, --path PATH Search for images in PATH (default: PWD) | |
| EOF | |
| } | |
| require() { | |
| command -v "${1}" &>/dev/null && return | |
| printf '%s\n' "Missing required application: '${1}'" >&2 | |
| return 1 | |
| } | |
| stitch() { | |
| ffmpeg \ | |
| -hide_banner \ | |
| -threads "0" \ | |
| -framerate "${1}" \ | |
| -pattern_type "glob" \ | |
| -i "${path}/*.${format}" \ | |
| -r "${1}" \ | |
| "${2}" | |
| } | |
| main() { | |
| local opts format | |
| opts="$(getopt \ | |
| --options hxf:p: \ | |
| --longoptions help,delete,format:,path: \ | |
| --name "${0##*/}" \ | |
| -- "${@}" \ | |
| )" | |
| format="png" | |
| path="${PWD}" | |
| eval set -- "${opts}" | |
| while true; do | |
| case "${1}" in | |
| -h | --help ) show_help; return 0;; | |
| -f | --format ) format="${2}";; | |
| -p | --path ) path="${2}";; | |
| -x | --delete ) del="1";; | |
| -- ) shift; break;; | |
| * ) break;; | |
| esac | |
| shift | |
| done | |
| if [[ -z "${1}" ]]; then | |
| printf '%s\n' "No framerate specified" >&2 | |
| return 1 | |
| elif [[ "${1}" =~ [^0-9.] ]]; then | |
| printf '%s\n' "Invalid FPS format: '${1}'" >&2 | |
| return 1 | |
| fi | |
| if ! [[ -d "${path}" ]]; then | |
| printf '%s\n' "Cannot locate directory: '${path}'" >&2 | |
| return 1 | |
| fi | |
| require 'ffmpeg' || return | |
| stitch "${1}" "${2:-${PWD}/stitch.mp4}" || return | |
| [[ -n "${del}" ]] && find "${path}" -type f -name "*.${format}" -delete | |
| return 0 | |
| } | |
| main "${@}" |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| #!/usr/bin/env bash | |
| # | |
| # Use webcam as a timelapse camera | |
| show_help() { | |
| cat << EOF | |
| Use webcam as a timelapse camera | |
| USAGE: ${0##*/} [OPTIONS] | |
| OPTIONS: | |
| -h, --help Show this help message | |
| -c, --camera DEV Use DEV as camera (default: '${settings['device']}') | |
| -d, --delay NUM Wait NUM seconds before capturing another frame (default: '${defaults['delay']}') | |
| -f, --font FILE Use font FILE for text rendering (default: '${defaults['font']}') | |
| -o, --outdir DIR Save frames to DIR (default: '${defaults['outdir']}') | |
| OUTDIR: | |
| The output directory can also be set with the TIMELAPSE_DIR environment | |
| variable. Additionally, -o will override the current TIMELAPSE_DIR value | |
| for that run. | |
| EOF | |
| } | |
| require() { | |
| command -v "${1}" &>/dev/null && return | |
| printf '%s\n' "Missing required application: '${1}'" >&2 | |
| return 1 | |
| } | |
| capture() { | |
| ffmpeg \ | |
| -y \ | |
| -hide_banner \ | |
| -err_detect 'ignore_err' \ | |
| -threads '0' \ | |
| -f 'video4linux2' \ | |
| -s '640x480' \ | |
| -i "${settings['device']}" \ | |
| -vf "drawtext=fontfile=${settings['font']}:text=%{localtime\:%T}:x=20:y=20:fontcolor=white" \ | |
| -vframes "1" \ | |
| "${settings['outdir']}/$(date '+%F-%H-%M').jpg" | |
| } | |
| main() { | |
| local -A defaults settings | |
| local opts i | |
| opts="$(getopt \ | |
| --options hc:d:f:o: \ | |
| --longoptions help,camera:,delay:,font:,outdir: \ | |
| --name "${0##*/}" \ | |
| -- "${@}" \ | |
| )" | |
| defaults['device']="/dev/video0" | |
| defaults['delay']="30" | |
| defaults['font']="/usr/share/fonts/truetype/dejavu/DeJaVuSansMono" | |
| defaults['outdir']="${TIMELAPSE_DIR:-${HOME}/.timelapse/$(date '+%F')}" | |
| for i in "${!defaults[@]}"; do settings["${i}"]="${defaults[$i]}"; done | |
| eval set -- "${opts}" | |
| while true; do | |
| case "${1}" in | |
| -h | --help ) show_help; return 0;; | |
| -c | --camera ) settings['device']="${2}"; shift;; | |
| -d | --delay ) settings['delay']="${2}"; shift;; | |
| -f | --font ) settings['font']="${2}"; shift;; | |
| -o | --outdir ) settings['outdir']="${2}"; shift;; | |
| -- ) shift; break;; | |
| * ) break;; | |
| esac | |
| shift | |
| done | |
| if ! [[ -e "${settings['device']}" ]]; then | |
| printf '%s\n' "Cannot locate camera: '${settings['device']}'" >&2 | |
| return 1 | |
| fi | |
| if ! [[ -s "${settings['font']}" ]]; then | |
| printf '%s\n' "Font file does not exist or is empty: '${settings['font']}'" >&2 | |
| return 1 | |
| fi | |
| if (( settings['delay'] <= 0 )); then | |
| printf '%s\n' "Delay must be greater than 0 seconds" >&2 | |
| return 1 | |
| fi | |
| require 'ffmpeg' || return 1 | |
| mkdir --parents "${settings['outdir']}" | |
| capture | |
| while true; do | |
| sleep "${settings['delay']}" | |
| capture | |
| done | |
| } | |
| main "${@}" |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| #!/usr/bin/env bash | |
| # | |
| # Translate text with translate.google.com | |
| show_help() { | |
| cat << EOF | |
| Translate text with translate.google.com | |
| USAGE: ${0##*/} [OPTIONS] LANG TEXT [...] | |
| OPTIONS: | |
| -h, --help Show this help message | |
| -l, --list Show a list of valid ISO 639-1 language codes | |
| EOF | |
| } | |
| urlencode() { | |
| xxd -plain <<< "${1}" | sed 's/\(..\)/%\1/g' | |
| } | |
| get_codes() { | |
| curl \ | |
| --silent \ | |
| --fail \ | |
| 'https://pkgstore.datahub.io/core/language-codes/language-codes_csv/data/b65af208b52970a4683fa8fde9af8e9f/language-codes_csv.csv' | |
| } | |
| get_uri() { | |
| local lang | |
| lang="${1}" | |
| shift | |
| printf 'http://translate.googleapis.com/translate_a/single?client=gtx&sl=auto&tl=%s&dt=t&q=%s\n' \ | |
| "${lang}" \ | |
| "$(urlencode "${*}")" | |
| } | |
| main() { | |
| local opts codes | |
| opts="$(getopt \ | |
| --options hl \ | |
| --longoptions help,list \ | |
| --name "${0##*/}" \ | |
| -- "${@}" \ | |
| )" | |
| codes="${XDG_DATA_HOME:-${HOME}/.local/share}/translate/codes.csv" | |
| eval set -- "${opts}" | |
| while true; do | |
| case "${1}" in | |
| -h | --help ) show_help; return 0;; | |
| -l | --list ) list="1";; | |
| -- ) shift; break;; | |
| * ) break;; | |
| esac | |
| shift | |
| done | |
| if [[ -n "${list}" ]]; then | |
| if ! [[ -s "${codes}" ]]; then | |
| mkdir --parents "${codes%/*}" | |
| get_codes > "${codes}" | |
| fi | |
| sed '1d;s/,/\t/;s/"//g' "${codes}" | column | |
| return | |
| fi | |
| if [[ -z "${1}" ]]; then | |
| printf '%s\n' "No language/text specified" >&2 | |
| return 1 | |
| elif [[ "${1}" != "${1:0:2}" ]]; then | |
| printf '%s\n' "Invalid language code: '${1}'" >&2 | |
| return 1 | |
| fi | |
| get_uri "${@}" | \ | |
| xargs -I {} curl --silent --fail "{}" 2>/dev/null | \ | |
| jq --monochrome-output '.[0][0][0]' | \ | |
| sed 's/^"\|"$//g' | |
| } | |
| main "${@}" |
Author
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
This was a first-pass rewrite of TheOuterLinux's bashrc file, which was posted to reddit 3 days ago.
The goal here was to both see if I could learn anything (which I did, thankfully); and to maybe provide an idea to TOL of what my previous feedback would look like...
Its still far from ideal in many ways; but I think it can still be helpful.