nutools/ufile

202 lines
6.3 KiB
Plaintext
Raw Normal View History

#!/bin/bash
# -*- coding: utf-8 mode: sh -*- vim:sw=4:sts=4:et:ai:si:sta:fenc=utf-8
source "$(dirname "$0")/lib/ulib/ulib" || exit 1
urequire DEFAULTS
function display_help() {
uecho "$scriptname: classer des fichiers selon certains règles
Les règles sont spécifiées dans le fichier ~/etc/default/ufile
Dans ce fichier, le tableau RULES contient des règles qui sont chacune de la
forme pattern:destdir[:renamef]
- pattern est au format glob et identifie les fichiers auxquels s'applique la
règle
- destdir est le répertoire de destination dans lequel classer le fichier
- renamef est une fonction qui permet de supporter le renommage d'un fichier
lors de son classement. Sa signature est 'renamef filename pf destdir' où
filename est le nom du fichier source, pf son chemin complet et destdir la
valeur de destdir mentionnée dans la règle.
La fonction doit définir la variable dest qui est le nouveau nom. Si la
fonction retourne un code d'erreur autre que zéro, la règle est ignorée.
Si le nouveau nom contient un chemin, destdir est ignoré et le fichier est
déplacé dans le répertoire spécifié.
2017-04-22 10:08:13 +04:00
Si dest est de la forme [user@]host:path alors le fichier est copié par scp
sur l'hôte spécifié vers la destination spécifiée, sauf si l'hôte courant est
déjà celui mentionné dans la valeur, auquel cas la copie est faite directement
dans le répertoire spécifié.
variables non documentées: interaction(=-i)
USAGE
$scriptname [options] <files...>
OPTIONS
-c, --config CONFIG
Utiliser le fichier de configuration spécifié au lieu de la valeur par
défaut ~/etc/default/ufile
-n, --fake
Afficher les opérations qui seraient faites
-l, --list
Lister les règles définies
-e, --edit
Lancer un éditeur sur le fichier de configuration"
}
function joinp() {
# afficher le chemin $1/$2
local pf="$1"
[ -n "$2" -a "${pf%/}" == "$pf" ] && pf="$pf/"
pf="$pf${2#/}"
echo "$pf"
}
args=(%
--help '$exit_with display_help'
-c:,--config: config=
2017-04-22 10:08:13 +04:00
-S:,--ssh: SSH=
-n,--fake fake=1
-l,--list action=list
-e,--edit action=edit
--file action=file
)
parse_args "$@"; set -- "${args[@]}"
[ -n "$action" ] || action=file
## charger toutes les règles
RULES=()
INCLUDES=()
if [ -n "$config" ]; then
if [ "$action" != edit ]; then
# le fichier doit exister, sauf en mode édition où il sera créé s'il
# n'existe pas déjà
[ -f "$config" ] || die "$config: fichier introuvable"
fi
if [ -f "$config" ]; then
source "$config" || die "$config: erreur lors de la lecture du fichier"
fi
else
set_defaults ufile
fi
array_copy rules RULES
for include in "${INCLUDES[@]}"; do
if [ -f "$include" ]; then
RULES=()
source "$include"
array_extend rules RULES
else
ewarn "$include: fichier introuvable"
fi
done
array_copy RULES rules
## actions particulières
if [ "$action" == list ]; then
echo "# $(echo_seta2 INCLUDES)"
array_to_lines RULES
exit 0
elif [ "$action" == edit ]; then
[ -n "$config" ] || setx config=get_user_defaults_file ufile
if [ ! -f "$config" ]; then
einfo "Le fichier $(ppath "$config") n'existe pas. Il sera créé avec un contenu par défaut"
mkdirof "$config" || die
cp "$scriptdir/lib/default/ufile" "$config"
fi
"${EDITOR:-vi}" "$config"
exit $?
2017-04-22 10:08:13 +04:00
elif [ "$action" != file ]; then
die "bug: $action: action non implémentée"
fi
## classement des fichiers
if [ -n "$fake" ]; then
function docmd() { qvals "$@"; }
else
function docmd() { "$@"; }
fi
[ $# -gt 0 ] || die "Vous devez spécifier des fichiers à classer"
[ ${#RULES[*]} -gt 0 ] || die "Vous devez spécifier des règles pour le classement des fichiers dans ~/etc/default/ufile"
# vérifier les règles
for rule in "${RULES[@]}"; do
splitpair "$rule" pattern r2
splitpair "$r2" destdir r3
splitpair "$r3" renamef r4
if [ -z "$destdir" -o "${destdir#"~/"}" != "$destdir" ]; then
:
elif [ "${destdir#/}" == "$destdir" ]; then
ewarn "$rule: règle potentiellement problématique: destdir devrait être absolu"
fi
done
# faire le classement effectif
for file in "$@"; do
[ -f "$file" -o -n "$fake" ] || {
eerror "$file: fichier introuvable. il sera ignoré"
continue
}
setx pf=abspath "$file"
setx dir=dirname -- "$pf"
setx filename=basename -- "$pf"
found=
for rule in "${RULES[@]}"; do
splitpair "$rule" pattern r2
splitpair "$r2" destdir r3
splitpair "$r3" renamef r4
if [ "${destdir#"~/"}" != "$destdir" ]; then
destdir="$HOME/${destdir#"~/"}"
fi
eval "[[ \"\$filename\" == $(qwc "$pattern") ]]" || continue
2017-04-22 10:08:13 +04:00
userhost=
destname="$filename"
2017-04-22 10:08:13 +04:00
interaction=-i
if [ -n "$renamef" ]; then
dest=
"$renamef" "$filename" "$pf" "$destdir" || continue
if [ -n "$dest" ]; then
2017-04-22 10:08:13 +04:00
if [[ "$dest" == *:* ]]; then
splitpair "$dest" userhost destdir
elif [[ "$dest" == */* ]]; then
setx dest=abspath "$dest"
setx destdir=dirname -- "$dest"
setx destname=dirname -- "$dest"
else
destname="$dest"
fi
fi
fi
2017-04-22 10:08:13 +04:00
if [ -z "$userhost" -a -z "$destdir" ]; then
eerror "$rule: règle invalide: destdir est vide"
break
fi
2017-04-22 10:08:13 +04:00
if [ -n "$userhost" ]; then
estep "$filename --> $dest"
ask_yesno $interaction "Voulez-vous continuer?" O || { found=x; break; }
docmd scp ${SSH:+-S "$SSH"} "$file" "$dest" || die "problème lors de la copie du fichier"
2017-04-22 10:08:13 +04:00
else
setx dest=joinp "$destdir" "$destname"
estep "$filename --> $dest"
ask_yesno $interaction "Voulez-vous continuer?" O || { found=x; break; }
docmd mkdir -p "$destdir" || die "$destdir: impossible de créer le répertoire"
docmd mv -i "$file" "$dest" || die "problème lors du déplacement du fichier"
fi
found=1
break
done
if [ -z "$found" ]; then
ewarn "$file: aucune correspondance n'a été trouvée"
fi
done