diff --git a/.gitignore b/.gitignore index 263f3c4..7296a55 100644 --- a/.gitignore +++ b/.gitignore @@ -14,7 +14,6 @@ dist/ downloads/ eggs/ .eggs/ -lib/ lib64/ parts/ sdist/ diff --git a/lib/completions.sh b/lib/completions.sh new file mode 100644 index 0000000..aa5d9c7 --- /dev/null +++ b/lib/completions.sh @@ -0,0 +1,126 @@ +_u7_complete_entities() { + local verb="$1" cur="$2" + case "$verb" in + show|sh) + COMPREPLY=($(compgen -W "ip csv json line ssl files diff cpu memory disk processes port usage network git env http docker system definition functions --help" -- "$cur")) + ;; + make|mk) + COMPREPLY=($(compgen -W "dir file password user copy link archive clone template sequence --help" -- "$cur")) + ;; + drop|dr) + COMPREPLY=($(compgen -W "file dir dirs files line lines column duplicates process user docker --help" -- "$cur")) + ;; + convert|cv) + COMPREPLY=($(compgen -W "archive files image video json yaml csv case spaces --help" -- "$cur")) + ;; + move|mv) + COMPREPLY=($(compgen -W "file sync --help" -- "$cur")) + ;; + set|st) + COMPREPLY=($(compgen -W "text slashes tabs perms owner --help" -- "$cur")) + ;; + run|rn) + COMPREPLY=($(compgen -W "job script check terminal --help" -- "$cur")) + ;; + esac +} + +_u7_complete_args() { + local verb="$1" entity="$2" cur="$3" + case "$verb" in + show|sh) + case "$entity" in + ip) COMPREPLY=($(compgen -W "external internal connected" -- "$cur")) ;; + processes) COMPREPLY=($(compgen -W "running by" -- "$cur")) ;; + files) COMPREPLY=($(compgen -W "match by" -- "$cur")) ;; + usage) COMPREPLY=($(compgen -W "disk directories" -- "$cur")) ;; + git) COMPREPLY=($(compgen -W "authors branches tags log status diff remotes" -- "$cur")) ;; + env) COMPREPLY=($(compgen -W "match" -- "$cur")) ;; + http) COMPREPLY=($(compgen -W "get head headers" -- "$cur")) ;; + docker) COMPREPLY=($(compgen -W "containers images volumes networks all" -- "$cur")) ;; + *) _filedir ;; + esac + ;; + make|mk) + case "$entity" in + copy|link) _filedir ;; + template) COMPREPLY=($(compgen -W "python node bash web" -- "$cur")) ;; + esac + ;; + drop|dr) + case "$entity" in + dirs) COMPREPLY=($(compgen -W "if" -- "$cur")) ;; + files) COMPREPLY=($(compgen -W "but" -- "$cur")) ;; + lines) COMPREPLY=($(compgen -W "if" -- "$cur")) ;; + docker) COMPREPLY=($(compgen -W "container image volume prune" -- "$cur")) ;; + *) _filedir ;; + esac + ;; + convert|cv) + case "$entity" in + archive|files) COMPREPLY=($(compgen -W "to" -- "$cur")) ;; + png|jpg|jpeg|gif) COMPREPLY=($(compgen -W "to" -- "$cur")) ;; + case) COMPREPLY=($(compgen -W "upper lower" -- "$cur")) ;; + spaces) COMPREPLY=($(compgen -W "to" -- "$cur")) ;; + *) _filedir ;; + esac + ;; + set|st) + case "$entity" in + slashes) COMPREPLY=($(compgen -W "back forward" -- "$cur")) ;; + tabs) COMPREPLY=($(compgen -W "to" -- "$cur")) ;; + perms|owner) COMPREPLY=($(compgen -W "to" -- "$cur")) ;; + *) _filedir ;; + esac + ;; + run|rn) + case "$entity" in + check) COMPREPLY=($(compgen -W "syntax" -- "$cur")) ; _filedir ;; + script) _filedir ;; + esac + ;; + esac +} + +_u7_completions() { + local cur prev words cword + _init_completion 2>/dev/null || { + cur="${COMP_WORDS[COMP_CWORD]}" + prev="${COMP_WORDS[COMP_CWORD-1]}" + words=("${COMP_WORDS[@]}") + cword=$COMP_CWORD + } + + local verbs="show sh make mk drop dr convert cv move mv set st run rn --help" + local opts="-n --dry-run" + + # Adjust for dry-run flag + local verb_idx=1 + if [[ "${words[1]}" == "-n" || "${words[1]}" == "--dry-run" ]]; then + verb_idx=2 + fi + local entity_idx=$((verb_idx + 1)) + + # Completing verb position + if [[ "$cword" -le "$verb_idx" ]]; then + if [[ "$cword" -eq 1 ]]; then + COMPREPLY=($(compgen -W "$verbs $opts" -- "$cur")) + else + COMPREPLY=($(compgen -W "$verbs" -- "$cur")) + fi + return + fi + + # Completing entity position + if [[ "$cword" -eq "$entity_idx" ]]; then + _u7_complete_entities "${words[$verb_idx]}" "$cur" + return + fi + + # Completing arguments + _u7_complete_args "${words[$verb_idx]}" "${words[$entity_idx]}" "$cur" +} + +if [[ $- == *i* ]]; then + complete -F _u7_completions u7 +fi diff --git a/lib/convert.sh b/lib/convert.sh new file mode 100644 index 0000000..901b5ab --- /dev/null +++ b/lib/convert.sh @@ -0,0 +1,295 @@ +_u7_archive_output_file() { + local archive="$1" + local dest="$2" + if [[ -d "$dest" ]]; then + local basename + basename=$(basename "$archive") + echo "$dest/${basename%.*}" + else + echo "$dest" + fi +} + +_u7_convert() { + local entity="$1" + shift + + case "$entity" in + archive) + local archive="$1" + if [[ "$2" != "to" || "$3" != "files" ]]; then + echo "Usage: u7 cv archive to files [yield ]" + return 1 + fi + local dest="." + if [[ "$4" == "yield" ]]; then + dest="$5" + fi + + if [[ ! -f "$archive" ]]; then + echo "Archive not found: $archive" + return 1 + fi + + local lowercase + lowercase=$(echo "$archive" | tr '[:upper:]' '[:lower:]') + + case "$lowercase" in + *.tar.xz|*.tar.gz|*.tar.bz2|*.tar|*.tgz|*.tbz|*.tbz2|*.txz|*.tb2) + _u7_exec tar -xvf "$archive" -C "$dest" ;; + *.bz|*.bz2) + _u7_exec bzip2 -d -k "$archive" ;; + *.gz) + local outfile + outfile=$(_u7_archive_output_file "$archive" "$dest") + if [[ "$_U7_DRY_RUN" == "1" ]]; then + echo "[dry-run] gunzip -c $archive > $outfile" + else + gunzip -c "$archive" > "$outfile" + fi + ;; + *.zip|*.jar) + _u7_exec unzip "$archive" -d "$dest" ;; + *.rar) + _u7_exec unrar x "$archive" "$dest" ;; + *.7z) + _u7_exec 7z x "$archive" "-o$dest" ;; + *.tar.lzma) + _u7_exec tar -xf "$archive" -C "$dest" --lzma ;; + *.xz) + local outfile + outfile=$(_u7_archive_output_file "$archive" "$dest") + if [[ "$_U7_DRY_RUN" == "1" ]]; then + echo "[dry-run] unxz -c $archive > $outfile" + else + unxz -c "$archive" > "$outfile" + fi + ;; + *.lzma) + local outfile + outfile=$(_u7_archive_output_file "$archive" "$dest") + if [[ "$_U7_DRY_RUN" == "1" ]]; then + echo "[dry-run] unlzma -c $archive > $outfile" + else + unlzma -c "$archive" > "$outfile" + fi + ;; + *.iso) + _u7_exec sudo mount -o loop "$archive" "$dest" ;; + *.img|*.dmg) + _u7_exec hdiutil mount "$archive" -mountpoint "$dest" ;; + *) + echo "Unknown archive format: $archive" + return 1 + ;; + esac + ;; + + files) + # Collect files until we hit "to archive" + local -a files=() + while [[ $# -gt 0 && "$1" != "to" ]]; do + files+=("$1") + shift + done + if [[ "$1" != "to" || "$2" != "archive" ]]; then + echo "Usage: u7 cv files to archive yield " + return 1 + fi + shift 2 + if [[ "$1" != "yield" ]]; then + echo "Usage: u7 cv files to archive yield " + return 1 + fi + local output="$2" + _u7_make archive "$output" from "${files[@]}" + ;; + + image) + local input="$1" + if [[ "$2" != "to" ]]; then + echo "Usage: u7 cv image to [yield ]" + return 1 + fi + local to_fmt="$3" + local output="${input%.*}.$to_fmt" + if [[ "$4" == "yield" ]]; then + output="$5" + fi + + case "$to_fmt" in + webp) + if ! _u7_require cwebp; then + echo "Falling back to ImageMagick for WebP conversion" + _u7_exec convert "$input" "$output" + else + _u7_exec cwebp -q 80 "$input" -o "$output" + fi + ;; + *) + _u7_exec convert "$input" "$output" + ;; + esac + ;; + + video) + local input="$1" + if [[ "$2" != "to" ]]; then + echo "Usage: u7 cv video to [yield ]" + return 1 + fi + local to_fmt="$3" + local output="${input%.*}.$to_fmt" + if [[ "$4" == "yield" ]]; then + output="$5" + fi + + case "$to_fmt" in + gif) + if ! _u7_require gifsicle; then + echo "Falling back to ffmpeg-only conversion" + _u7_exec ffmpeg -i "$input" "$output" + else + if [[ "$_U7_DRY_RUN" == "1" ]]; then + echo "[dry-run] ffmpeg -i $input -pix_fmt rgb24 -r 10 -f gif - | gifsicle --optimize=3 --delay=5 > $output" + else + ffmpeg -i "$input" -pix_fmt rgb24 -r 10 -f gif - | gifsicle --optimize=3 --delay=5 > "$output" + fi + fi + ;; + *) + _u7_exec ffmpeg -i "$input" "$output" + ;; + esac + ;; + + json) + local input="$1" + if [[ "$2" != "to" ]]; then + echo "Usage: u7 cv json to yaml [yield ]" + return 1 + fi + local to_fmt="$3" + local output="${input%.*}.$to_fmt" + if [[ "$4" == "yield" ]]; then + output="$5" + fi + + case "$to_fmt" in + yaml|yml) + if [[ "$_U7_DRY_RUN" == "1" ]]; then + echo "[dry-run] yq -P < $input > $output" + else + yq -P < "$input" > "$output" + fi + ;; + *) echo "Unsupported conversion: json to $to_fmt" ; return 1 ;; + esac + ;; + + csv) + local input="$1" + if [[ "$2" != "to" ]]; then + echo "Usage: u7 cv csv to json [yield ]" + return 1 + fi + local to_fmt="$3" + local output="${input%.*}.$to_fmt" + if [[ "$4" == "yield" ]]; then + if [[ -z "$5" ]]; then + echo "Usage: u7 cv csv to json [yield ]" + return 1 + fi + output="$5" + fi + + if [[ ! -f "$input" ]]; then + echo "File not found: $input" + return 1 + fi + + case "$to_fmt" in + json) + _u7_require qsv || return 1 + if [[ "$_U7_DRY_RUN" == "1" ]]; then + echo "[dry-run] qsv tojsonl $input > $output" + else + local tmpfile + tmpfile=$(mktemp "${output}.XXXXXX") || { echo "Error: Failed to create temp file"; return 1; } + qsv tojsonl "$input" > "$tmpfile" && mv "$tmpfile" "$output" || { rm -f "$tmpfile"; return 1; } + fi + ;; + *) echo "Unsupported conversion: csv to $to_fmt" ; return 1 ;; + esac + ;; + + case) + if ! _u7_require rename "rename (perl-rename or prename)"; then + echo "Hint: Install 'rename' package (perl-rename on Debian/Ubuntu, rename on others)" + return 1 + fi + if [[ "$1" == "upper" && "$2" == "to" && "$3" == "lower" ]]; then + if [[ "$4" != "on" ]]; then + echo "Usage: u7 cv case upper to lower on " + return 1 + fi + # Convert only basename to lowercase, preserve extension case + _u7_exec rename 's/^(.*)(\.\w+)$/lc($1) . $2/e' "${@:5}" + elif [[ "$1" == "lower" && "$2" == "to" && "$3" == "upper" ]]; then + if [[ "$4" != "on" ]]; then + echo "Usage: u7 cv case lower to upper on " + return 1 + fi + # Convert only basename to uppercase, preserve extension case + _u7_exec rename 's/^(.*)(\.\w+)$/uc($1) . $2/e' "${@:5}" + else + echo "Usage: u7 cv case to on " + fi + ;; + + spaces) + if ! _u7_require rename "rename (perl-rename or prename)"; then + echo "Hint: Install 'rename' package (perl-rename on Debian/Ubuntu, rename on others)" + return 1 + fi + if [[ "$1" == "to" && "$2" == "underscores" ]]; then + if [[ "$3" != "on" ]]; then + echo "Usage: u7 cv spaces to underscores on " + return 1 + fi + if [[ -n "$4" ]]; then + _u7_exec rename 'y/ /_/' "$4" + else + _u7_exec rename 'y/ /_/' -- * + fi + else + echo "Usage: u7 cv spaces to underscores on " + fi + ;; + + --help|-h) + cat << 'EOF' +u7 cv (convert) - Transform/Extract + +Usage: u7 cv to [yield ] + +Entities: + archive to files [yield ] Extract archive + files to archive yield Create archive + image to [yield ] Convert image (png/jpg/webp/gif/etc) + video to [yield ] Convert video + json to yaml [yield ] Convert JSON to YAML + csv to json [yield ] Convert CSV to JSON + case upper to lower on Rename to lowercase + case lower to upper on Rename to uppercase + spaces to underscores on Replace spaces in filenames +EOF + ;; + + *) + echo "Unknown entity: $entity" + echo "Run 'u7 cv --help' for usage" + return 1 + ;; + esac +} diff --git a/lib/core.sh b/lib/core.sh new file mode 100644 index 0000000..c7e833a --- /dev/null +++ b/lib/core.sh @@ -0,0 +1,37 @@ +# Check if a command is available +_u7_require() { + local cmd="$1" + local msg="${2:-$cmd}" + if ! command -v "$cmd" &> /dev/null; then + echo "Error: Required command '$cmd' not found." + echo "Install it or run in 'nix develop' shell for full functionality." + return 1 + fi + return 0 +} + +# Escape special regex characters for literal sed replacement +_u7_escape_sed() { + local str="$1" + # Escape sed special chars: \ first, then . * [ ] ^ $ / + str="${str//\\/\\\\}" # Escape backslash + str="${str//\//\\/}" # Escape forward slash + str="${str//./\\.}" # Escape dot + str="${str//\*/\\*}" # Escape asterisk + str="${str//\[/\\[}" # Escape [ + str="${str//\]/\\]}" # Escape ] + str="${str//\^/\\^}" # Escape ^ + str="${str//\$/\\$}" # Escape $ + printf '%s' "$str" +} + +# Dry-run mode: show command without executing +_U7_DRY_RUN=0 + +_u7_exec() { + if [[ "$_U7_DRY_RUN" == "1" ]]; then + echo "[dry-run] $*" + else + "$@" + fi +} diff --git a/lib/drop.sh b/lib/drop.sh new file mode 100644 index 0000000..5e3e1eb --- /dev/null +++ b/lib/drop.sh @@ -0,0 +1,164 @@ +_u7_drop() { + local entity="$1" + shift + + case "$entity" in + file) + if [[ -z "$1" ]]; then + echo "Usage: u7 dr file " + return 1 + fi + _u7_exec rm -i "$1" + ;; + + dir) + if [[ -z "$1" ]]; then + echo "Usage: u7 dr dir " + return 1 + fi + _u7_exec rm -ri "$1" + ;; + + dirs) + if [[ "$1" == "if" && "$2" == "empty" ]]; then + _u7_exec find . -type d -empty -delete + [[ "$_U7_DRY_RUN" != "1" ]] && echo "Deleted empty directories" + else + echo "Usage: u7 dr dirs if empty" + fi + ;; + + files) + if [[ "$1" == "but" ]]; then + local pattern="$2" + if [[ "$_U7_DRY_RUN" == "1" ]]; then + echo "[dry-run] find . -type f ! -name $pattern -delete" + else + echo "This will delete all files but '$pattern'. Continue? (y/n)" + read -r confirm + if [[ "$confirm" == "y" ]]; then + find . -type f ! -name "$pattern" -delete + else + echo "Aborted." + fi + fi + else + echo "Usage: u7 dr files but " + fi + ;; + + line) + local num="$1" + if [[ "$2" != "from" ]]; then + echo "Usage: u7 dr line from " + return 1 + fi + local file="$3" + if [[ -z "$num" || -z "$file" ]]; then + echo "Usage: u7 dr line from " + return 1 + fi + if [[ "$_U7_DRY_RUN" == "1" ]]; then + echo "[dry-run] sed -i'' ${num}d $file" + else + sed -i'' "${num}d" "$file" + fi + ;; + + lines) + if [[ "$1" == "if" && "$2" == "blank" && "$3" == "from" && "$5" == "yield" ]]; then + local src="$4" + local dst="$6" + if [[ "$_U7_DRY_RUN" == "1" ]]; then + echo "[dry-run] grep . $src > $dst" + else + grep . "$src" > "$dst" + fi + else + echo "Usage: u7 dr lines if blank from yield " + fi + ;; + + column) + local num="$1" + if [[ "$2" != "from" ]]; then + echo "Usage: u7 dr column from " + return 1 + fi + local file="$3" + if [[ -z "$num" || -z "$file" ]]; then + echo "Usage: u7 dr column from " + return 1 + fi + if [[ "$_U7_DRY_RUN" == "1" ]]; then + echo "[dry-run] cut -d',' -f$num --complement $file" + else + local tmpfile + tmpfile=$(mktemp "${file}.XXXXXX") || { echo "Error: Failed to create temp file"; return 1; } + cut -d',' -f"$num" --complement "$file" > "$tmpfile" && mv "$tmpfile" "$file" || { rm -f "$tmpfile"; return 1; } + fi + ;; + + duplicates) + if [[ "$1" != "in" && "$1" != "from" ]]; then + echo "Usage: u7 dr duplicates in|from " + return 1 + fi + local file="$2" + if [[ -z "$file" ]]; then + echo "Usage: u7 dr duplicates in|from " + return 1 + fi + if [[ "$_U7_DRY_RUN" == "1" ]]; then + echo "[dry-run] awk '!x[\$0]++' $file" + else + local tmpfile + tmpfile=$(mktemp "${file}.XXXXXX") || { echo "Error: Failed to create temp file"; return 1; } + awk '!x[$0]++' "$file" > "$tmpfile" && mv "$tmpfile" "$file" || { rm -f "$tmpfile"; return 1; } + fi + ;; + + process) + local pid="$1" + if [[ -z "$pid" ]]; then + echo "Usage: u7 dr process " + return 1 + fi + _u7_exec kill "$pid" + ;; + + user) + if [[ -z "$1" ]]; then + echo "Usage: u7 dr user " + return 1 + fi + _u7_exec sudo deluser "$1" + ;; + + --help|-h) + cat << 'EOF' +u7 dr (drop) - Delete/Kill + +Usage: u7 dr [arguments] + +Entities: + file Delete file (with confirmation) + dir Delete directory (with confirmation) + dirs if empty Delete all empty directories + files but Delete all files but + line from Delete line from file + lines if blank from yield Remove blank lines + column from Delete column from CSV + duplicates in|from Remove duplicate lines + process Kill process + user Delete system user +EOF + ;; + + *) + echo "Unknown entity: $entity" + echo "Run 'u7 dr --help' for usage" + return 1 + ;; + esac +} diff --git a/lib/make.sh b/lib/make.sh new file mode 100644 index 0000000..c349105 --- /dev/null +++ b/lib/make.sh @@ -0,0 +1,215 @@ +_u7_make() { + local entity="$1" + shift + + case "$entity" in + dir) + _u7_exec mkdir -p "$1" + ;; + + file) + _u7_exec touch "$1" + ;; + + password) + local length + if [[ "$1" == "length" ]]; then + length="${2:-16}" + else + length="${1:-16}" + fi + LC_ALL=C tr -dc 'A-Za-z0-9!@#$%^&*' < /dev/urandom | head -c "$length" + echo + ;; + + user) + if [[ -z "$1" ]]; then + echo "Usage: u7 mk user " + return 1 + fi + _u7_exec sudo useradd "$1" + ;; + + copy) + local src="$1" + if [[ "$2" != "to" ]]; then + echo "Usage: u7 mk copy to " + return 1 + fi + local dst="$3" + _u7_exec cp -r "$src" "$dst" + ;; + + link) + local src="$1" + if [[ "$2" != "to" ]]; then + echo "Usage: u7 mk link to " + return 1 + fi + local dst="$3" + _u7_exec ln -s "$src" "$dst" + ;; + + archive) + local output="$1" + if [[ "$2" != "from" ]]; then + echo "Usage: u7 mk archive from " + return 1 + fi + shift 2 + local format="${output##*.}" + case "$format" in + gz) + if [[ "$output" == *.tar.gz ]]; then + _u7_exec tar -czvf "$output" "$@" + else + if [[ "$_U7_DRY_RUN" == "1" ]]; then + echo "[dry-run] gzip -c $* > $output" + else + gzip -c "$@" > "$output" + fi + fi + ;; + bz2) + if [[ "$output" == *.tar.bz2 ]]; then + _u7_exec tar -cjvf "$output" "$@" + else + if [[ "$_U7_DRY_RUN" == "1" ]]; then + echo "[dry-run] bzip2 -c $* > $output" + else + bzip2 -c "$@" > "$output" + fi + fi + ;; + xz) + if [[ "$output" == *.tar.xz ]]; then + _u7_exec tar -cJvf "$output" "$@" + else + if [[ "$_U7_DRY_RUN" == "1" ]]; then + echo "[dry-run] xz -c $* > $output" + else + xz -c "$@" > "$output" + fi + fi + ;; + zip) _u7_exec zip -r "$output" "$@" ;; + 7z) _u7_exec 7z a "$output" "$@" ;; + tar) _u7_exec tar -cvf "$output" "$@" ;; + *) echo "Unsupported format: $format" ; return 1 ;; + esac + ;; + + clone) + local repo="$1" + if [[ -z "$repo" ]]; then + echo "Usage: u7 mk clone [to ]" + return 1 + fi + local dest="" + if [[ "$2" == "to" && -n "$3" ]]; then + dest="$3" + fi + if [[ -n "$dest" ]]; then + _u7_exec git clone "$repo" "$dest" + else + _u7_exec git clone "$repo" + fi + ;; + + template) + local tmpl="$1" + local name="$2" + if [[ -z "$tmpl" || -z "$name" ]]; then + echo "Usage: u7 mk template " + return 1 + fi + if [[ ! "$name" =~ ^[a-zA-Z0-9_-]+$ ]]; then + echo "Error: project name must contain only alphanumerics, hyphens, and underscores" + return 1 + fi + if [[ -d "$name" ]]; then + echo "Error: directory '$name' already exists" + return 1 + fi + if [[ "$_U7_DRY_RUN" == "1" ]]; then + echo "[dry-run] Create $tmpl project: $name" + return 0 + fi + case "$tmpl" in + python) + mkdir -p "$name/src" "$name/tests" + echo "# $name" > "$name/README.md" + echo "#!/usr/bin/env python3" > "$name/src/main.py" + touch "$name/src/__init__.py" "$name/tests/__init__.py" + echo "Created Python project: $name" + ;; + node) + _u7_require jq || return 1 + mkdir -p "$name/src" "$name/test" + echo "# $name" > "$name/README.md" + jq -n --arg name "$name" '{"name": $name, "version": "0.1.0", "main": "src/index.js"}' > "$name/package.json" + echo "// $name" > "$name/src/index.js" + echo "Created Node project: $name" + ;; + bash) + mkdir -p "$name" + echo "# $name" > "$name/README.md" + printf '#!/usr/bin/env bash\nset -euo pipefail\n\necho '\''Hello from %s'\''\n' "$name" > "$name/main.sh" + chmod +x "$name/main.sh" + echo "Created Bash project: $name" + ;; + web) + mkdir -p "$name/css" "$name/js" + local escaped_name="${name///>}" + echo "$escaped_name

$escaped_name

" > "$name/index.html" + touch "$name/css/style.css" "$name/js/main.js" + echo "Created Web project: $name" + ;; + *) echo "Unknown template: $tmpl. Available: python, node, bash, web" ; return 1 ;; + esac + ;; + + sequence) + if [[ "$1" != "with" || "$2" != "prefix" ]]; then + echo "Usage: u7 mk sequence with prefix limit " + return 1 + fi + local prefix="$3" + if [[ "$4" != "limit" ]]; then + echo "Usage: u7 mk sequence with prefix limit " + return 1 + fi + local count="$5" + for i in $(seq 1 "$count"); do + echo "${prefix}_${i}" + done + ;; + + --help|-h) + cat << 'EOF' +u7 mk (make) - Create/Clone + +Usage: u7 mk [arguments] + +Entities: + dir Create directory at + file Create empty file + password length Generate random password of length + user Create system user + copy to Copy file/directory + link to Create symbolic link + archive from Create archive from to + clone [to ] Git clone a repository + template Scaffold a project structure + sequence with prefix limit Generate numbered sequence with prefix and limit +EOF + ;; + + *) + echo "Unknown entity: $entity" + echo "Run 'u7 mk --help' for usage" + return 1 + ;; + esac +} diff --git a/lib/move.sh b/lib/move.sh new file mode 100644 index 0000000..5e45a2f --- /dev/null +++ b/lib/move.sh @@ -0,0 +1,44 @@ +_u7_move() { + local entity="$1" + shift + + case "$entity" in + file) + local src="$1" + if [[ "$2" == "to" ]]; then + local dst="$3" + _u7_exec mv "$src" "$dst" + else + echo "Usage: u7 mv file to " + return 1 + fi + ;; + sync) + local src_dir="$1" + if [[ "$2" == "to" ]]; then + local dst_dir="$3" + _u7_exec rsync -avz "$src_dir" "$dst_dir" + else + echo "Usage: u7 mv sync to " + return 1 + fi + ;; + --help|-h) + cat << 'EOF' +u7 mv (move) - Relocate/Rename + +Usage: u7 mv file to + u7 mv sync to + +Examples: + u7 mv file notes.txt to /backup/ + u7 mv file old.txt to new.txt + u7 mv sync local/ to remote/ +EOF + ;; + *) + echo "Usage: u7 mv file to " + return 1 + ;; + esac +} diff --git a/lib/run.sh b/lib/run.sh new file mode 100644 index 0000000..a25aa53 --- /dev/null +++ b/lib/run.sh @@ -0,0 +1,125 @@ +_u7_run() { + local entity="$1" + shift + + case "$entity" in + job) + local cmd="$1" + if [[ "$2" != "in" ]]; then + echo "Usage: u7 rn job in