#!/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