Files
wcx_script/mvi.sh
2025-10-09 10:55:52 +02:00

107 lines
2.4 KiB
Bash
Executable File

#!/usr/bin/env bash
set -euo pipefail
usage() {
cat <<'EOF'
Användning:
mvi KÄLLA MÅL
mvi KÄLLA1 KÄLLA2 ... KATALOG
Flyttar som 'mv', men om en målfil redan finns så läggs ett index in
före filändelsen, t.ex. "fil.txt" -> "fil.1.txt", "fil.2.txt", ...
Exempel:
mvi bild.jpg bilder/ # bilder/bild.jpg eller bilder/bild.1.jpg
mvi .env prod/ # prod/.env eller prod/.env.1
mvi projekt/ arkiv/ # arkiv/projekt eller arkiv/projekt.1
EOF
}
# Ta reda på om sista argumentet är en katalog (målet när flera källor)
is_dir() {
local p=$1
[[ -d "$p" ]]
}
# Skapa ett indexerat fil-/katalognamn om target redan finns.
# Regler:
# - index (".N") injiceras före sista filändelsen
# - för dolda filer utan ändelse (t.ex. ".env"): ".env.1"
# - för flera punkter (t.ex. "fil.tar.gz"): "fil.tar.1.gz"
indexed_path() {
local target="$1"
local dir base name ext n candidate
dir=$(dirname -- "$target")
name=$(basename -- "$target")
# Dela upp name i bas + ev. ext (sista punkten räknas som extension-separator)
if [[ "$name" = .* && "$name" != *.* ]]; then
# Dold fil utan extension (".env")
base="$name"
ext=""
elif [[ "$name" = *.* ]]; then
base="${name%.*}"
ext=".${name##*.}"
else
base="$name"
ext=""
fi
n=1
while :; do
candidate="${dir}/${base}.${n}${ext}"
[[ ! -e "$candidate" ]] && { printf '%s\n' "$candidate"; return 0; }
n=$((n+1))
done
}
# Flytta en enskild källa till ett givet mål (fil eller katalog)
move_one() {
local src="$1"
local dst="$2"
local target
if [[ -d "$dst" ]]; then
target="${dst%/}/$(basename -- "$src")"
else
target="$dst"
fi
if [[ -e "$target" ]]; then
target=$(indexed_path "$target")
fi
# Skapa målkatalog om den inte finns (som mv gör med -t dir om den finns)
mkdir -p -- "$(dirname -- "$target")"
mv -- "$src" "$target"
}
# --- Huvudprogram ---
if [[ $# -lt 2 ]]; then
usage
exit 1
fi
# Sista arg är destination
dest="${@: -1}"
sources=("${@:1:$(($#-1))}")
# Om flera källor: dest måste vara katalog
if [[ ${#sources[@]} -gt 1 ]]; then
if ! is_dir "$dest"; then
echo "Fel: Flera källor kräver att destinationen är en katalog." >&2
exit 2
fi
fi
# Iterera över alla källor
for src in "${sources[@]}"; do
if [[ ! -e "$src" ]]; then
echo "Varning: källan finns inte: $src" >&2
continue
fi
move_one "$src" "$dest"
done