bash : update autocompletes.

This commit is contained in:
Dmitry Voronin 2023-10-30 03:49:10 +03:00
parent 7fe861d541
commit 12d31e883c
18 changed files with 371 additions and 304 deletions

View file

@ -300,10 +300,29 @@ Those are self-written scripts to create archives. They are basically compressed
Command|Description
---|---
`archive [DIRS]`|Create archive with the best compression (slow). If no args given, archives all files in current directory as separate archives.
`archive_fast [DIRS]`|Like normal `archive` but with minimal compression.
`archive_check [DIRS]`|Check specified archives or all archives in current directory.
`unarchive [DIRS]`|Check specified or all archives and extract if they are correct.
`archive [FILES]`|Create archive with the best compression (slow). If no args given, archives all files in current directory as separate archives.
`archive_fast [FILES]`|Like normal `archive` but with minimal compression.
`archive_check [ARCHIVES]`|Check specified archives or all archives in current directory.
`archive_name [ARCHIVES] [NAME]`|Rename specified archive ro specified name or simplify name for specified archive or simplify names for all archives.
`unarchive [ARCHIVES]`|Check specified or all archives and extract if they are correct.
## Autocomplete.
Thos are functions that provide tab-completions.
```bash
_foo()
{
_autocomplete "{foo,bar}"
}
complete -F _foo foo
```
Command|Description
---|---
`_autocomplete <ARGS>`|Provide completion based on provided arguments separated by spaces.
`_autocomplete_first <ARGS>`|Same as `_autocomplete` but works only once for first argument.
`_autocomplete_nested`|Provides nested completions, just like `sudo` does.
## Battery.
@ -333,11 +352,12 @@ Command|Description
Command|Description
---|---
`x [FILE]`|Make file executable.
`x <FILE>`|Make file executable.
## Color.
### How to use.
Most of the time you want to use it with `echo`. To make `echo` respect colors, you need to use `-e` flag like that:
```bash
export color_default="\033[0m"
@ -347,6 +367,7 @@ echo -e "${color_red}hello world!${color_default}" # will print "hello world!" i
Don't forget to use `color_default` at the end, or your whole terminal will be red.
### List of colors.
Please note that colors depend on Terminal Emulator and may vary based on its settings.
|Color|Code|
@ -378,10 +399,10 @@ Command|Description
Command|Description
---|---
`cp [FROM] [TO]`|Copy files or dirs. Actually, it is an alias for `rsync -ahP`.
`cp_merge [FROM] [TO]`|Mirror directories. Same as `rsync --delete`.
`cp_link`|Copy directory by recursively creating hardlinks and directories.
`bcp`|Default `cp` command.
`cp <FROM> <TO>`|Copy files or dirs. Actually, it is an alias for `rsync -ahP`. Multiple `<FROM>` could be specified.
`cp_merge <FROM> <TO>`|Mirror directories. Same as `rsync --delete`.
`cp_link <FROM> <TO>`|Copy directory by recursively creating hardlinks and directories.
`bcp <FROM> <TO>`|Default `cp` command.
## Date.
@ -402,16 +423,16 @@ Command|Description
Command|Description
---|---
`df`|Show free disk space (only physical media).
`du [DIR]`|Show disk usage.
`du [FILES]`|Show disk usage.
## Docker.
Command|Description
---|---
`docker_volumes [CONTAINER]`|Show volumes of a specified container.
`docker_volumes <CONTAINER>`|Show volumes of a specified container.
`docker_health`|Show containers that exited with an error code.
`docker_prune`|Heavy cleanup to free up space.
`docker_ip [CONTAINER]`|Show IP of a specified container.
`docker_ip <CONTAINER>`|Show IP of a specified container.
`docker_update`|Update all Docker images.
`dc`|Short for `docker compose`.
`dcu [SERVICE]`|Start a compose service.
@ -440,13 +461,13 @@ Variable|Description
Command|Description
---|---
`ffmpeg_mux_audio [SOUND] [RESULT]`|Mux external audio into one container with video (replaces original audio). Run inside dir with original video. [SOUND] names should be the same for each video.
`ffmpeg_mux_audio <SOUND> <RESULT>`|Mux external audio into one container with video (replaces original audio). Run inside dir with original video. <SOUND> names should be the same for each video.
## Files.
Command|Description
---|---
`o [FILE]`|Open file with default GUI app.
`o <FILE>`|Open file with default GUI app.
## Fix.
@ -454,7 +475,7 @@ Contains simple fixes for warious issues.
Command|Description
---|---
`fix_ethernet_speed [SPEED]`|Specify ethernet speed if it failed to set correct speed automatically. [SPEED] can be 10/100/1000 etc.
`fix_ethernet_speed <SPEED>`|Specify ethernet speed if it failed to set correct speed automatically. [SPEED] can be 10/100/1000 etc.
`fix_files_sftp`|Make Nautilus forget incorrect password for SFTP connection.
## Git.
@ -503,22 +524,22 @@ Command|Description
`name [FILES]`|Replace all non-alphanumeric characters in file with underscores.
`name_hash [FILES]`|Replace all file names with hashes, keep extension.
`name_hash_check [FILES]`|Check all file hashes.
`name_series [SEASON]`|Rename files to Jellyfin's show format: `Episode S01E01.mkv`.
`name_manga [SEASON]`|Rename files to Kavita's manga format: `Name Vol.1 Ch.01.cbr`.
`name_ext [EXTENSION] [FILES]`|Change file extensions.
`name_series <SEASON>`|Rename files to Jellyfin's show format: `Episode S01E01.mkv`.
`name_manga <SEASON>`|Rename files to Kavita's manga format: `Name Vol.1 Ch.01.cbr`.
`name_ext <EXTENSION> [FILES]`|Change file extensions.
## Ncdu.
Command|Description
---|---
`ncdu`|Show recursive disk usage. Only on the same filesystem.
`ncdu [DIR]`|Show recursive disk usage. Only on the same filesystem.
## Notify.
Command|Description
---|---
`notify`|Send notification.
`notify_silent`|Send silent notification.
`notify <MESSAGE>`|Send notification.
`notify_silent <MESSAGE>`|Send silent notification.
## Own.
@ -537,12 +558,12 @@ Command|Description
Command|Description
---|---
`ps [PROGRAM]`|Show process info for matching [PROGRAM] name.
`ps <PROGRAM>`|Show process info for matching [PROGRAM] name.
## Recursive.
Command|Description
---|---
`recursive [COMMAND]`|Cd into every directory recursively and run specified command in each dir.
`recursive <COMMAND>`|Cd into every directory recursively and run specified command in each dir.
## Shopt.
@ -568,12 +589,12 @@ Command|Description
Command|Description
---|---
`ta [NAME]`|Attach to session by name.
`ta [NAME]`|Attach to session by name. Default is `main`.
`td`|Detach from session.
`tl`|List all sessions.
`tr`|Rename session.
`tn`|Name window.
`tk [NAME]`|Kill session.
`tk [NAME]`|Kill session. Default is `main`.
`tka`|Kill all sessions.
## To-do.
@ -586,16 +607,16 @@ Command|Description
Command|Description
---|---
`tb [NAME]`|Attach to box by name.
`tbk [NAME]`|Kill box by name.
`tb_rpmfusion [NAME]`|Install RPMFusion package to box by name.
`tb [NAME]`|Attach to box by name. Default is `main`.
`tbk [NAME]`|Kill box by name. Default is `main`.
`tb_rpmfusion [NAME]`|Install RPMFusion package to box by name. Default is `main`.
`tbl`|List all boxes.
## Try.
Command|Description
---|---
`try`|Repeat the command every 2 seconds until it exits with success.
`try <COMMAND>`|Repeat the command every 2 seconds until it exits with success.
## Umask.
@ -605,8 +626,8 @@ By default, umask is `077` which means group and others have no access when file
Command|Description
---|---
`vdl [LINK]`|Download video/playlist.
`vdl_file [FILE]`|Download all links from a file.
`vdl <LINK>`|Download video/playlist.
`vdl_file <FILE>`|Download all links from a file.
`vdl_update`|Update playlist that was downloaded with `vdl` before.
`vdl_update_all`|Recursive `vdl_update`.
@ -620,11 +641,11 @@ Command|Description
Command|Description
---|---
`wallpaper [FILE]`|Set specified file as a wallpaper.
`wallpaper <FILE>`|Set specified file as a wallpaper.
## Watch.
Command|Description
---|---
`w [COMMAND]`|Alias for `watch`.
`ww [COMMAND]`|Alias for `watch` that updates every 0.1 seconds.
`w <COMMAND>`|Alias for `watch`.
`ww <COMMAND>`|Alias for `watch` that updates every 0.1 seconds.

View file

@ -1,8 +1,8 @@
#!/bin/bash
#home="/var/home/voronind"
home="$HOME"
module="$home/document/linux/config/bash/module"
home="${HOME}"
module="${home}/document/linux/config/bash/module/*.sh"
# src default
if [[ -f /etc/bashrc ]]; then
@ -10,8 +10,8 @@ if [[ -f /etc/bashrc ]]; then
fi
# src custom
for file in $(ls "$module"); do
source "$module/$file"
for file in ${module}; do
source "${file}"
done
# alias to reload

View file

@ -0,0 +1,7 @@
# Help page for scripting.
# Conventions.
## Bash manpage arguments.
`[OPTIONAL] <REQUIRED> {DEFAULT} (INFO)`

View file

@ -1,91 +1,97 @@
# archive file with maximum compression and checksum.
# usage: archive [FILES]
archive()
{
local target="$@" # target file(s).
local count=0 # processed count.
local total=$# # total to process.
local targets=("${@}") # target file(s).
local count=0 # processed count.
local total=${#} # total to process.
# set dafult value to target all supported archives.
if [[ "${target}" = "" ]]; then
target="*"
total=$(ls | wc -l)
if [[ "${targets}" = "" ]]; then
targets=(*)
total=${#targets[@]}
fi
# iterate each file.
for file in ${target}; do
# iterate each target.
for target in "${targets[@]}"; do
# increment counter.
((count++))
# status info.
local status="[${count}/${total}] ${file}"
local status="[${count}/${total}] ${target}"
echo "${status}"
# create archive.
tar -c "${file}" | pv -s $(du -sb "${file}" | awk '{print $1}') | xz -9e > "${file%/*}".tar.xz
tar -c "${target}" | pv -s $(du -sb "${target}" | awk '{print $1}') | xz -9e > "${target%/*}".tar.xz
# append hash to file name.
mv "${file%/*}".tar.xz "${file%/*}"_$(sha1sum "${file%/*}".tar.xz | cut -d\ -f1).tar.xz
# append hash to target name.
mv "${target%/*}".tar.xz "${target%/*}"_$(sha1sum "${target%/*}".tar.xz | cut -d\ -f1).tar.xz
done
}
# archive file with minimal compression and checksum.
# usage: archive_fast [FILES]
archive_fast()
{
local target="$@" # target file(s).
local count=0 # processed count.
local total=$# # total to process.
local targets=("${@}") # target file(s).
local count=0 # processed count.
local total=${#} # total to process.
# set dafult value to target all supported archives.
if [[ "${target}" = "" ]]; then
target="*"
total=$(ls | wc -l)
if [[ "${targets}" = "" ]]; then
targets=(*)
total=${#targets[@]}
fi
# iterate each file.
for file in ${target}; do
# iterate each target.
for target in "${targets[@]}"; do
# increment counter.
((count++))
# status info.
local status="[${count}/${total}] ${file}"
local status="[${count}/${total}] ${target}"
echo "${status}"
# create archive.
tar -c "${file}" | pv -s $(du -sb "${file}" | awk '{print $1}') | gzip -1 > "${file%/*}".tar.gz
tar -c "${target}" | pv -s $(du -sb "${target}" | awk '{print $1}') | gzip -1 > "${target%/*}".tar.gz
# append hash to file name.
mv "${file%/*}".tar.gz "${file%/*}"_$(sha1sum "${file%/*}".tar.gz | cut -d\ -f1).tar.gz
# append hash to target name.
mv "${target%/*}".tar.gz "${target%/*}"_$(sha1sum "${target%/*}".tar.gz | cut -d\ -f1).tar.gz
done
}
# check archive hashes.
# usage: archive_check [FILES]
archive_check()
{
local target="$@" # target file(s).
local count=0 # processed count.
local total=$# # total to process.
local failed=0 # total failed checks.
local targets=("${@}") # target file(s).
local total=${#} # total to process.
local count=0 # processed count.
local failed=0 # total failed checks.
# set dafult value to target all supported archives.
if [[ "${target}" = "" ]]; then
target="*_*.tar.*"
total=$(ls ${target} | wc -l)
if [[ "${targets}" = "" ]]; then
targets=(*_*.tar.*)
total=${#targets[@]}
fi
# iterate each file.
for file in ${target}; do
# iterate each target.
for target in "${targets[@]}"; do
# process only files.
[[ -f "${target}" ]] || continue
# increment counter.
((count++))
# status info.
local status="[${count}/${total}] ${file}"
local status="[${count}/${total}] ${target}"
# extract hash from name.
local saved="${file##*_}"
local saved="${target##*_}"
saved="${saved%%.*}"
# calculate actual hash.
local actual="$(pv ${file} | sha1sum | cut -d\ -f1)"
local actual=$(pv "${target}" | sha1sum | cut -d\ -f1)
# compare hashes, show error on mismatch.
if [[ "${actual}" = "${saved}" ]]; then
@ -107,78 +113,102 @@ archive_check()
}
# extract previously created archive with checksum validation.
# usage: unarchive [FILES]
unarchive()
{
local target="$@" # target file(s).
local count=0 # processed count.
local total=$# # total to process.
local targets=("${@}") # target file(s).
local count=0 # processed count.
local total=${#} # total to process.
# set dafult value to target all supported archives.
if [[ "${target}" = "" ]]; then
target="*_*.tar.*"
total=$(ls ${target} | wc -l)
if [[ "${targets}" = "" ]]; then
targets=(*_*.tar.*)
total=${#targets[@]}
fi
# iterate each file.
for file in ${target}; do
# iterate each target.
for target in "${targets[@]}"; do
# increment counter.
((count++))
# status info.
local status="[${count}/${total}] ${file}"
local status="[${count}/${total}] ${target}"
# extract hash from name.
local saved="${file##*_}"
local saved="${target##*_}"
saved="${saved%%.*}"
# calculate actual hash.
local actual="$(sha1sum ${file} | cut -d\ -f1)"
local actual=$(sha1sum "${target}" | cut -d\ -f1)
# extract if hash matched or show error if not.
if [[ "${saved}" = "${actual}" ]]; then
echo "${status}: OK."
tar -xf "${file}"
tar -xf "${target}"
else
echo "${status}: failed."
fi
done
}
# rename archive.
# usage: archive_rename [ARCHIVE] [NAME]
archive_rename()
# rename archive. if no name specified, it simplifies archive's name.
# usage: archive_name [ARCHIVE] [NAME]
archive_name()
{
# get params.
local target="${1}"
local name="${2}"
local targets="${1}" # target archive(s).
local name="${2}" # new name.
local total=1 # total targets to process.
local count=0 # processed targets counter.
# check params.
if [[ "${target}" = "" || "${name}" = "" ]]; then
echo "usage: archive_rename [ARCHIVE] [NAME]"
return 1
# set dafult value to target all supported archives.
if [[ "${targets}" = "" ]]; then
targets=(*_*.tar.*)
total=${#targets[@]}
fi
# remove old name.
local data="${target##*_}"
local new_name="${name}_${data}"
# iterate each target.
for target in "${targets[@]}"; do
# only work with targets.
[[ -f "${target}" ]] || continue
# prepare status.
local status="${target} -> ${new_name}"
# iterate counter.
((count++))
# rename.
mv -- "${target}" "${new_name}" && echo "${status}" || echo -e "${color_red}${status}: error.${color_default}"
# simplify name by default.
if [[ "${name}" = "" || ${count} -gt 1 ]]; then
name="${target%_*}"
name="$(parse_alnum ${name})"
fi
# remove old name.
local data="${target##*_}"
local new_name="${name}_${data}"
# prepare status.
local status="[${count}/${total}] ${target} -> ${new_name}"
# check for the same name.
if [[ "${target}" = "${new_name}" ]]; then
echo -e "${color_green}${status}: no change.${color_default}"
continue
fi
# check for existing target.
if [[ -f "${new_name}" ]]; then
echo -e "${color_red}${status}: already exists.${color_default}"
return 1
fi
# rename.
mv -- "${target}" "${new_name}" && echo "${status}" || echo -e "${color_red}${status}: error.${color_default}"
done
}
# export everything, primarily for use with parallel..
export -f archive archive_fast archive_check unarchive
export -f archive archive_fast archive_check unarchive archive_name
# autocomplete.
_archive_list()
{
_autocomplete "$(ls *_*.tar.* 2> /dev/null)"
}
_archive_rename()
_archive_name()
{
COMPREPLY=()
@ -187,7 +217,7 @@ _archive_rename()
local command="${COMP_WORDS[0]}"
if [[ "${prev}" = "${command}" ]]; then
COMPREPLY=( $(compgen -W "$(ls -a)" -- ${cur}) )
COMPREPLY=( $(compgen -W "$(ls *_*.tar.*)" -- ${cur}) )
return 0
else
local name="${prev%_*}"
@ -196,5 +226,5 @@ _archive_rename()
fi
}
complete -o plusdirs -F _archive_list archive_check unarchive
complete -F _archive_rename archive_rename
complete -f -X "!*_*.tar.*" archive_check unarchive
complete -F _archive_name archive_name

View file

@ -1,9 +1,9 @@
# bash autocomplete.
# usage: _foo () { _autocomplete "{foo,bar}" } ; complete -F _foo foo
# usage: _foo() { _autocomplete "{foo,bar}" } ; complete -F _foo foo
# there are also options like -o nospace. see man for more info.
_autocomplete()
{
local commands="$@"
local commands="${@}"
COMPREPLY=()
@ -18,7 +18,7 @@ _autocomplete()
# autocomplete only first argument.
_autocomplete_first()
{
local commands="$@"
local commands="${@}"
COMPREPLY=()
@ -32,26 +32,6 @@ _autocomplete_first()
fi
}
# autocomplete only first argument. the rest is ls output.
_autocomplete_first_ls()
{
local commands="$@"
COMPREPLY=()
local cur="${COMP_WORDS[COMP_CWORD]}"
local prev="${COMP_WORDS[COMP_CWORD-1]}"
local command="${COMP_WORDS[0]}"
if [[ "${prev}" = "${command}" ]]; then
COMPREPLY=( $(compgen -W "${commands}" -- ${cur}) )
return 0
else
COMPREPLY=( $(compgen -W "$(ls -a)" -- ${cur}) )
return 0
fi
}
# autocomplete nested program.
_autocomplete_nested()
{
@ -62,7 +42,7 @@ _autocomplete_nested()
if [[ ${words[i]} != -* ]]; then
local PATH=$PATH:/sbin:/usr/sbin:/usr/local/sbin
local root_command=${words[i]}
_command_offset $i
_command_offset ${i}
return
fi
done

View file

@ -1,4 +1,6 @@
# create or check checksums for all files in current directory.
# usage: checksum <ACTION>
# actions: "new", "check".
checksum()
{
local action="$1" # what to do with checksum.

View file

@ -1,2 +1,2 @@
alias copy="wl-copy"
alias paste="wl-paste"
alias copy="wl-copy" # copy stdin to system clipboard.
alias paste="wl-paste" # paste system clipboard to stdout.

View file

@ -1,2 +1,2 @@
alias dconf_load="dconf load / < $HOME/document/linux/config/gnome.dconf"
alias dconf_save="dconf dump / > $HOME/document/linux/config/_gnome.dconf"
alias dconf_load="dconf load / < $HOME/document/linux/config/gnome.dconf" # load gnome settings.
alias dconf_save="dconf dump / > $HOME/document/linux/config/_gnome.dconf" # dump gnome settings to a file.

View file

@ -8,6 +8,7 @@ alias docker_health="docker ps -a | grep Exited"
alias docker_prune="docker system prune --volumes --all"
# short aliases.
# usage: dc [SERVICE]
alias dc="docker compose"
alias dcu="docker compose up -d"
alias dcd="docker compose down"
@ -16,24 +17,31 @@ alias dcl="docker compose logs -f"
alias dcr="docker compose restart"
alias dcs="docker compose stop"
# down & up specified services.
# usage: dcdu [SERVICES]
dcdu()
{
dcd "${@}"
dcu "${@}"
}
# pull & up specified services.
# usage: dcpu [SERVICES]
dcpu()
{
dcp "${@}"
dcu "${@}"
}
# up & attach to logs for specified services.
# usage: dcul [SERVICES]
dcul()
{
dcu "${@}" && dcl "${@}"
}
# find out container's IP address.
# usage: docker_up <CONTAINER NAME>
docker_ip()
{
docker inspect -f '\''{{range .NetworkSettings.Networks}}{{.IPAddress}}{{end}}'\' $1 | sed "s/^.//" | sed "s/.$//"

View file

@ -1,8 +1,9 @@
# mux audio into containers. tmp usage for anime downloads.
# mux audio into containers. file names in sound and current dirrectories must match. tmp usage for anime downloads.
# usage: ffmpeg_mux_audio <SOUND> <OUTPUT DIR>
ffmpeg_mux_audio()
{
if [[ "$1" = "" ]]; then
echo "usage: $ sound/ result/"
echo "usage: ffmpeg_mux_audio <SOUND> <OUTPUT DIR>"
return
fi

View file

@ -1,2 +1,3 @@
# open file/dir in GUI.
# usage: o <FILE>
alias o="xdg-open"

View file

@ -1,15 +1,17 @@
# fix when ethernet mistakenly detects 100 Mb instead of 1000 Mb.
# usage: fix_ethernet_speed <DEVICE> <SPEED>
# SPEED is one of 10/100/1000 etc.
fix_ethernet_speed()
{
local device="$1"
local speed="$2"
local device="${1}"
local speed="${2}"
if [[ "$device" = "" || "$speed" = "" ]]; then
echo "usage: [device] [speed]"
if [[ "${device}" = "" || "${speed}" = "" ]]; then
echo "usage: fix_ethernet_speed <DEVICE> <SPEED>"
return 1
fi
ethtool -s "$device" speed "$speed"
ethtool -s "${device}" speed "${speed}"
}
# fix files wrong sftp password.

View file

@ -23,14 +23,22 @@ git_tag()
git log | grep commit -m1 | sed -e "s/.*\ //g" | cut -c 1-11;
}
# alias to preview diff while adding.
# alias to preview diff while adding. adds current dir by default.
# usage: ga [FILES]
ga()
{
git diff $@
git add $@
local target=${@}
if [[ "${target}" = "" ]]; then
target="."
fi
git diff ${target}
git add ${target}
}
# rebase by X commits or from root.
# rebase by X commits or from root. when COUNT is 0 - rebase from root. default is 2.
# usage: gr [COMMIT COUNT]
gr()
{
local base="${1}"
@ -88,7 +96,7 @@ fi
_gu()
{
_autocomplete account@voronind.com dd.voronin@fsight.ru
_autocomplete_first account@voronind.com dd.voronin@fsight.ru
}
complete -F _gu gu

View file

@ -15,19 +15,20 @@ ll()
}
# list files in tree structure.
# usage: lll [DEPTH] [FILES]
lll()
{
local depth="$1"
local paths="${@:2}"
local depth="${1}"
local target="${@:2}"
if [[ "$paths" = "" ]]; then
paths="."
if [[ "${target}" = "" ]]; then
target="."
fi
if [[ "$depth" = "" ]]; then
tree -a -- "$paths"
if [[ "${depth}" = "" ]]; then
tree -a -- "${target}"
else
tree -a -L "$depth" -- "$paths"
tree -a -L "${depth}" -- "${target}"
fi
}

View file

@ -2,49 +2,41 @@
# usage: name [FILES]
name()
{
local files="$@"
local count=0
local total=$#
local IFS=$'\n'
local targets=("${@}") # target file(s).
local count=0 # processed count.
local total=${#} # total to process.
# all files except hidden by default.
if [[ "${files}" = "" ]]; then
files="[^.]*"
total=$(ls | wc -l)
# all targets except hidden by default.
if [[ "${targets}" = "" ]]; then
targets=([^.]*)
total=${#targets[@]}
fi
# process.
for file in ${files}; do
# increment count.
for target in "${targets[@]}"; do
# increment counter.
((count++))
# extract new name.
local new_name=$(echo "${file}" | \
sed -e "s/ /_/g" \
-e "s/[^[:alnum:]\._-]//g" \
-e "s/_\+/_/g" -e "s/\.\+/\./g" -e "s/-\+/-/g" \
-e "s/_-/_/g" -e "s/-_/_/g" -e "s/\.-/\./g" -e "s/-\./\./g" -e "s/\._/\./g" -e "s/_\./\./g" \
-e "s/_\+/_/g" \
-e "s/^_//" -e "s/_$//"
)
# parse new name.
local new_name=$(parse_simplify "${target}")
# status line.
local status="[${count}/${total}] ${file} -> ${new_name}"
local status="[${count}/${total}] ${target} -> ${new_name}"
# check if same name.
if [[ "${file}" = "${new_name}" ]]; then
if [[ "${target}" = "${new_name}" ]]; then
echo -e "${color_green}${status}: no change.${color_default}"
continue
fi
# check if file name already exists.
# check if target name already exists.
if [[ -f "${new_name}" ]]; then
echo -e "${color_red}${status}: already exists!${color_default}"
return 1
fi
# rename file.
mv -- "${file}" "${new_name}" &> /dev/null
# rename target.
mv -- "${target}" "${new_name}" &> /dev/null
# show change.
echo "${status}"
@ -55,51 +47,50 @@ name()
# usage: name_hash [FILES]
name_hash()
{
local files="$@"
local count=0
local total=$#
local IFS=$'\n'
local targets=("${@}") # target file(s).
local count=0 # processed counter.
local total=${#} # total to process.
# all files except hidden by default.
if [[ "${files}" = "" ]]; then
files="[^.]*"
total=$(ls -p | grep -v / | wc -l)
# all targets except hidden by default.
if [[ "${targets}" = "" ]]; then
targets=([^.]*)
total=${#targets[@]}
fi
# process.
for file in ${files}; do
# process only files.
if [[ -f "${file}" ]]; then
# increment count.
((count++))
for target in "${targets[@]}"; do
# process only targets.
[[ -f "${target}" ]] || continue
# extract extension.
local extension="${file##*.}"
if [[ "${extension}" = "${file}" ]]; then
extension=""
else
extension=".${extension}"
fi
# increment count.
((count++))
# hash the new name.
local hash=$(sha1sum -- "${file}" | cut -d\ -f1)
new_name="${hash,,}${extension}"
# prepare status.
local status="[${count}/${total}] ${file} -> ${new_name}"
# check if same name.
if [[ "${file}" = "${new_name}" ]]; then
echo -e "${color_green}${status}: no change.${color_default}"
continue
fi
# rename file.
mv -- "${file}" "${new_name}" &> /dev/null
# show change.
echo -e "${status}"
# extract extension.
local extension="${target##*.}"
if [[ "${extension}" = "${target}" ]]; then
extension=""
else
extension=".${extension}"
fi
# hash the new name.
local hash=$(sha1sum -- "${target}" | cut -d\ -f1)
new_name="${hash,,}${extension}"
# prepare status.
local status="[${count}/${total}] ${target} -> ${new_name}"
# check if same name.
if [[ "${target}" = "${new_name}" ]]; then
echo -e "${color_green}${status}: no change.${color_default}"
continue
fi
# rename target.
mv -- "${target}" "${new_name}" &> /dev/null
# show change.
echo -e "${status}"
done
}
@ -107,31 +98,30 @@ name_hash()
# usage: name_hash_check [FILES]
name_hash_check()
{
local files="$@"
local count=0
local total=$#
local failed=0
local IFS=$'\n'
local targets=("${@}") # target file(s).
local total=${#} # total to process.
local count=0 # processed counter.
local failed=0 # failed to process counter.
# all files by default.
if [[ "${files}" = "" ]]; then
files="[^.]*"
total=$(ls -p | grep -v / | wc -l)
# all targets by default.
if [[ "${targets}" = "" ]]; then
targets=([^.]*)
total=${#target[@]}
fi
# process.
for file in ${files}; do
# process only files.
if [[ -f "${file}" ]]; then
for target in "${targets[@]}"; do
# process only targets.
if [[ -f "${target}" ]]; then
# increment count.
((count++))
# status info.
local status="[${count}/${total}] ${file}"
local status="[${count}/${total}] ${target}"
# extract hashes.
local stored="${file%%.*}"
local actual=$(sha1sum -- "${file}" | cut -d\ -f1)
local stored="${target%%.*}"
local actual=$(sha1sum -- "${target}" | cut -d\ -f1)
# compare hashes.
if [[ "${stored}" = "${actual}" ]]; then
@ -154,127 +144,127 @@ name_hash_check()
}
# rename files for Jellyfin series, i.e. Episode S01E01.mkv
# usage: name_series [SEASON]
# usage: name_series <SEASON>
name_series()
{
local season="${1}"
local files="${@:2}"
local count=0
local total=$#
local IFS=$'\n'
local season="${1}" # season number.
local targets="${@:2}" # target files.
local count=0 # processed counter.
local total=${#} # total to process.
# error when no season number specified.
if [[ "${season}" = "" ]]; then
echo "usage: name_series [SEASON]"
echo "usage: name_series <SEASON>"
return 1
fi
# all files by default.
if [[ "${files}" = "" ]]; then
files="[^.]*"
total=$(ls -p | grep -v / | wc -l)
# all targets by default.
if [[ "${targets}" = "" ]]; then
targets=([^.]*)
total=${#targets[@]}
fi
# process.
for file in ${files}; do
# process only files.
if [[ -f "${file}" ]]; then
for target in "${targets[@]}"; do
# process only targets.
if [[ -f "${target}" ]]; then
# increment episode number.
((count++))
# extract new name.
local new_name="Episode S${season}E$(printf %02d ${count}).${file##*.}"
local new_name="Episode S${season}E$(printf %02d ${count}).${target##*.}"
# prepare status.
local status="[${count}/${total}] ${file} -> ${new_name}"
local status="[${count}/${total}] ${target} -> ${new_name}"
# rename file.
mv -- "${file}" "${new_name}" &> /dev/null
# rename target.
mv -- "${target}" "${new_name}" &> /dev/null
echo -e "${status}"
fi
done
}
# rename files for Kavita manga format.
# usage: name_manga [SEASON]
# usage: name_manga <SEASON>
name_manga()
{
local season="$1"
local files="${@:2}"
local count=0
local total=$#
local manga="${PWD##*/}"
local IFS=$'\n'
local season="${1}" # season number.
local targets="${@:2}" # target files.
local count=0 # processed counter.
local total=${#} # total to process.
local manga="${PWD##*/}" # manga name.
# error when no season number specified.
if [[ "${season}" = "" ]]; then
echo "usage: name_manga [SEASON]"
echo "usage: name_manga <SEASON>"
return 1
fi
# all files by default.
if [[ "${files}" = "" ]]; then
files="[^.]*"
total=$(ls -p | grep -v / | wc -l)
# all targets by default.
if [[ "${targets}" = "" ]]; then
targets=([^.]*)
total=${#targets[@]}
fi
# process.
for file in ${files}; do
# process only files.
if [[ -f "${file}" ]]; then
for target in "${targets[@]}"; do
# process only targets.
if [[ -f "${target}" ]]; then
# increment episode number.
((count++))
# extract new name.
local new_name="${manga} Vol.${season} Ch.${count}.${file##*.}"
local new_name="${manga} Vol.${season} Ch.${count}.${target##*.}"
# prepare status.
local status="[${count}/${total}] ${file} -> ${new_name}"
local status="[${count}/${total}] ${target} -> ${new_name}"
# rename file.
mv -- "${file}" "${new_name}" &> /dev/null
# rename target.
mv -- "${target}" "${new_name}" &> /dev/null
echo -e "${status}"
fi
done
}
# rename files for new extension.
# usage: name_ext [EXTENSION] [FILES]
# usage: name_ext <EXTENSION> [FILES]
name_ext()
{
local extension="$1"
local files="${@:2}"
local count=0
local total=$#
local IFS=$'\n'
local extension="${1}" # new extension.
local targets="${@:2}" # target file(s).
local count=0 # processed counter.
local total=${#} # total to process.
# remove extension name from total files.
((total--))
# error when no new extension specified.
if [[ "${extension}" = "" ]]; then
echo "usage: name_ext [EXTENSION] [FILES]"
echo "usage: name_ext <EXTENSION> [targets]"
return 1
fi
# all files by default.
if [[ "${files}" = "" ]]; then
files="[^.]*"
total=$(ls -p | grep -v / | wc -l)
# all targets by default.
if [[ "${targets}" = "" ]]; then
targets=([^.]*)
total=${#targets[@]}
fi
# process.
for file in ${files}; do
# process only files.
if [[ -f "${file}" ]]; then
for target in "${targets[@]}"; do
# process only targets.
if [[ -f "${target}" ]]; then
# increment count.
((count++))
# extract new name.
local new_name="${file%.*}"."${extension}"
local new_name="${target%.*}"."${extension}"
# rename file.
mv -- "${file}" "${new_name}" &> /dev/null
# rename target.
mv -- "${target}" "${new_name}" &> /dev/null
# show change.
echo "[${count}/${total}] ${file} -> ${new_name}"
echo "[${count}/${total}] ${target} -> ${new_name}"
fi
done
}

View file

@ -1,4 +1,5 @@
# change file ownership to specified user id and restrict access to him.
# usage: own [USER] [FILES]
own()
{
local file="${2}"
@ -20,11 +21,3 @@ own()
# remove access from group and others.
chmod -077 -R "${file}"
}
# autocomplete.
_own()
{
_autocomplete_first_ls "{0,1000}"
}
complete -F _own own

View file

@ -0,0 +1,20 @@
# parse data and output simplified format.
# usage: parse_simplify <STRING>
parse_simplify()
{
echo "${*}" | \
sed -e "s/ /_/g" \
-e "s/[^[:alnum:]\._-]//g" \
-e "s/_\+/_/g" -e "s/\.\+/\./g" -e "s/-\+/-/g" \
-e "s/_-/_/g" -e "s/-_/_/g" -e "s/\.-/\./g" -e "s/-\./\./g" -e "s/\._/\./g" -e "s/_\./\./g" \
-e "s/_\+/_/g" \
-e "s/^_//" -e "s/_$//"
}
# parse data keeping only alphanumeric characters.
# usage: parse_alnum <STRING>
parse_alnum()
{
echo "${*}" | \
sed -e "s/[^[:alnum:]]//g"
}

View file

@ -1,11 +1,12 @@
# create toolbx container with default or specified name.
# usage: tb [NAME]
tb()
{
local name="$1"
# set default name.
if [[ "$name" = "" ]]; then
name="toolbx"
name="main"
fi
# start container or run command inside it if specified.
@ -37,13 +38,14 @@ tb()
}
# remove toolbx container with default or specified name.
# usage: tbk [NAME]
tbk()
{
local name="$1"
# set default name.
if [[ "$name" = "" ]]; then
name="toolbx"
name="main"
fi
# stop and remove podman container.
@ -51,13 +53,14 @@ tbk()
}
# install rpm-fusion repository.
# usage: tb_rpmfusion [NAME]
tb_rpmfusion()
{
local name="$1"
# set default name.
if [[ "$name" = "" ]]; then
name="toolbx"
name="main"
fi
# run dnf inside container.
@ -70,7 +73,7 @@ alias tbl="toolbox list -c"
# autocomplete.
_tb_containers()
{
_autocomplete "$(toolbox list -c | sed -e '1d' | awk '{ print $2 }')"
_autocomplete_first "$(toolbox list -c | sed -e '1d' | awk '{ print $2 }')"
}
complete -F _tb_containers tb tbk tb_rpmfusion