first commit
This commit is contained in:
106
mvi.sh
Executable file
106
mvi.sh
Executable file
@ -0,0 +1,106 @@
|
||||
#!/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
|
||||
Reference in New Issue
Block a user