ufile: possibilité de classer vers plusieurs destinations

This commit is contained in:
Jephté Clain 2017-04-25 08:27:09 +04:00
parent 8c22012d13
commit 262048fee5
1 changed files with 114 additions and 53 deletions

151
ufile
View File

@ -21,16 +21,19 @@ forme pattern:destdir[:renamef]
La fonction doit définir la variable dest qui est le nouveau nom. Si la 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. 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 Si le nouveau nom contient un chemin, destdir est ignoré et le fichier est
déplacé dans le répertoire spécifié. déplacé dans le répertoire spécifié avec le nom spécifié. Si dest est un
tableau avec plusieurs destinations, alors le fichier est copié en plusieurs
fois.
Si dest est de la forme [user@]host:path alors le fichier est copié par scp 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 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 déjà celui mentionné dans la valeur, auquel cas la copie est faite directement
dans le répertoire spécifié. dans le répertoire spécifié.
Si le user et l'hôte courant sont déjà à la valeur spécifiée, alors la copie Si le user et l'hôte courant sont déjà à la valeur spécifiée, alors la copie
est faite en local sans utiliser scp. Cependant, path est alors le chemin est faite en local sans utiliser scp sauf si l'option --force-scp est utilisée
complet vers le fichier destination. Si on veut copier le fichier sans le Le chemin spécifié, en local ou distant, est toujours le chemin complet vers
renommer vers un répertoire, il faut mettre un slash e.g user@host:destdir/ le fichier destination. Si on veut copier le fichier sans le renommer vers un
variables non documentées: interaction(=-i) répertoire, il faut mettre un slash e.g destdir/ ou user@host:destdir/
variables pouvant être définies mais non documentées: interaction(=-i)
USAGE USAGE
$scriptname [options] <files...> $scriptname [options] <files...>
@ -39,6 +42,15 @@ OPTIONS
-c, --config CONFIG -c, --config CONFIG
Utiliser le fichier de configuration spécifié au lieu de la valeur par Utiliser le fichier de configuration spécifié au lieu de la valeur par
défaut ~/etc/default/ufile défaut ~/etc/default/ufile
--file
Classer les fichiers spécifiés. C'est l'action par défaut
-S, --ssh SSH
S'il faut classer sur un hôte distant avec scp, utiliser le programme
spécifié pour la connexion par ssh
--force-scp
Toujours utiliser scp pour une copie distante. Par défaut s'il est
déterminé que l'hôte distant est en réalité l'hôte courant, alors la
copie est effectuée directement.
-n, --fake -n, --fake
Afficher les opérations qui seraient faites Afficher les opérations qui seraient faites
-l, --list -l, --list
@ -55,14 +67,52 @@ function joinp() {
echo "$pf" echo "$pf"
} }
function __check_destdir() {
local destdir="$1" rule="$2"
if [ -z "$destdir" ]; then
eerror "$rule: règle invalide: destdir est vide"
return 1
fi
return 0
}
function __set_dest() {
local dest="$1" destdir="$2" filename="$3" force_scp="$4"
local userhost remotedir destname
if [[ "$dest" == *:* ]]; then
splitpair "$dest" userhost remotedir
if [ -z "$force_scp" ] && check_userhostname "$userhost"; then
# on est déjà avec le bon user sur le bon hôte
if [ -n "$remotedir" ]; then
splitpath "$remotedir" destdir destname
setx destdir=abspath "$destdir" "$HOME"
[ -n "$destname" ] || destname="$filename"
setx dest=joinp "$destdir" "$destname"
else
setx dest=joinp "$HOME" "$filename"
fi
fi
elif [[ "$dest" == */* ]]; then
splitpath "$dest" destdir destname
[ -n "$destname" ] || destname="$filename"
setx dest=joinp "$destdir" "$destname"
setx dest=abspath "$dest"
else
__check_destdir "$destdir" "$rule" || return 1
setx dest=joinp "$destdir" "$filename"
fi
upvar dest "$dest"
return 0
}
args=(% args=(%
--help '$exit_with display_help' --help '$exit_with display_help'
-c:,--config: config= -c:,--config: config=
--file action=file
-S:,--ssh: SSH= -S:,--ssh: SSH=
--force-scp force_scp=1
-n,--fake fake=1 -n,--fake fake=1
-l,--list action=list -l,--list action=list
-e,--edit action=edit -e,--edit action=edit
--file action=file
) )
parse_args "$@"; set -- "${args[@]}" parse_args "$@"; set -- "${args[@]}"
@ -139,6 +189,7 @@ for rule in "${RULES[@]}"; do
done done
# faire le classement effectif # faire le classement effectif
r=
for file in "$@"; do for file in "$@"; do
[ -f "$file" -o -n "$fake" ] || { [ -f "$file" -o -n "$fake" ] || {
eerror "$file: fichier introuvable. il sera ignoré" eerror "$file: fichier introuvable. il sera ignoré"
@ -150,66 +201,76 @@ for file in "$@"; do
found= found=
for rule in "${RULES[@]}"; do for rule in "${RULES[@]}"; do
splitpair "$rule" pattern r2 splitpair "$rule" pattern r2
splitpair "$r2" destdir r3 splitpair "$r2" odestdir r3
splitpair "$r3" renamef r4 splitpair "$r3" renamef r4
if [ "${destdir#"~/"}" != "$destdir" ]; then if [ "${odestdir#"~/"}" != "$odestdir" ]; then
destdir="$HOME/${destdir#"~/"}" odestdir="$HOME/${odestdir#"~/"}"
elif [ "$odestdir" == "~" ]; then
odestdir="$HOME"
fi fi
eval "[[ \"\$filename\" == $(qwc "$pattern") ]]" || continue eval "[[ \"\$filename\" == $(qwc "$pattern") ]]" || continue
userhost= unset dest
destname="$filename"
interaction=--DEFAULT-- interaction=--DEFAULT--
if [ -n "$renamef" ]; then if [ -n "$renamef" ]; then
dest= "$renamef" "$filename" "$pf" "$odestdir" || continue
"$renamef" "$filename" "$pf" "$destdir" || continue
if [ -n "$dest" ]; then
if [[ "$dest" == *:* ]]; then
splitpair "$dest" userhost remotedir
if check_userhostname "$userhost"; then
# on est déjà avec le bon user sur le bon hôte
userhost=
if [ -n "$remotedir" ]; then
[ "$interaction" == --DEFAULT-- ] && interaction=
splitpath "$remotedir" destdir destname
[ -n "$destname" ] || destname="$filename"
fi fi
fi if is_array dest; then
elif [[ "$dest" == */* ]]; then array_copy tmpdests dest
setx dest=abspath "$dest" dests=()
setx destdir=dirname -- "$dest" for dest in "${tmpdests[@]}"; do
setx destname=dirname -- "$dest" __set_dest "$dest" "$odestdir" "$filename" "$force_scp" || break
array_add dests "$dest"
done
elif is_defined dest; then
__set_dest "$dest" "$odestdir" "$filename" "$force_scp" || break
dests=("$dest")
else else
destname="$dest" __check_destdir "$odestdir" "$rule" || break
fi setx dest=joinp "$odestdir" "$filename"
fi dests=("$dest")
fi
[ "$interaction" == --DEFAULT-- ] && interaction=-i
if [ -z "$userhost" -a -z "$destdir" ]; then
eerror "$rule: règle invalide: destdir est vide"
break
fi fi
if [ -n "$userhost" ]; then i=1
mvi=${#dests[*]}
for dest in "${dests[@]}"; do
if [[ "$dest" == *:* ]]; then
[ "$interaction" == --DEFAULT-- ] && int= || int="$interaction"
estep "$filename --> $dest" estep "$filename --> $dest"
ask_yesno $interaction "Voulez-vous continuer?" O || { found=x; break; } ask_yesno $int "Voulez-vous continuer?" O || {
r=1; found=x; break
}
docmd scp ${SSH:+-S "$SSH"} "$file" "$dest" || die "problème lors de la copie du fichier" docmd scp ${SSH:+-S "$SSH"} "$file" "$dest" || die "problème lors de la copie du fichier"
else else
setx dest=joinp "$destdir" "$destname" [ "$interaction" == --DEFAULT-- ] && int=-i || int="$interaction"
estep "$filename --> $dest" estep "$filename --> $dest"
ask_yesno $interaction "Voulez-vous continuer?" O || { found=x; break; } ask_yesno $int "Voulez-vous continuer?" O || {
r=1; found=x; break
}
setx destdir=dirname -- "$dest"
docmd mkdir -p "$destdir" || die "$destdir: impossible de créer le répertoire" 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" if [ $i -eq $mvi ]; then
mvdesc="du déplacement"
mvcmd=mv
else
mvdesc="de la copie"
mvcmd=cp
fi fi
found=1 docmd "$mvcmd" -i "$file" "$dest" || die "problème lors $mvdesc du fichier"
fi
i=$(($i + 1))
done
[ -n "$found" ] || found=1
break break
done done
if [ -z "$found" ]; then if [ -z "$found" ]; then
ewarn "$file: aucune correspondance n'a été trouvée" ewarn "$file: aucune correspondance n'a été trouvée"
fi fi
done done
[ -n "$r" ] || r=0
exit $r