#!/bin/bash # -*- coding: utf-8 mode: sh -*- vim:sw=4:sts=4:et:ai:si:sta:fenc=utf-8 TOOLS=(ddir dfile dcopy dmove dcmd) if [ "$#" -eq 1 -a "$1" == --nutools-makelinks ]; then # créer les liens scriptname="$(basename "$0")" for tool in "${TOOLS[@]}"; do ln -s "$scriptname" "$tool" done exit 0 fi source "$(dirname -- "$0")/lib/ulib/auto" || exit 1 function display_help() { uecho "$scriptname: manipuler des noms de fichier pour les dater USAGE $scriptname (FILE|DIR)s... $scriptname -k SRCs... [DESTDIR] $scriptname -m SRCs... [DESTDIR] $scriptname -c COMMAND [ARGs...] OPTIONS --create-or-rename Créer un nouveau fichier (option -f) ou créer un nouveau répertoire (option -d), ou renommer un fichier existant sans le changer de répertoire. C'est l'option par défaut. -f, --create-file Créer un nouveau fichier. Cette option est ignorée si le fichier ou le répertoire spécifié existe. C'est la valeur par défaut -d, --create-dir Créer un nouveau répertoire. Cette option est ignorée si le fichier ou le répertoire spécifié existe. -k, --copy Copier le fichier SRC vers la destination DESTDIR qui vaut par défaut le répertoire courant si un seul fichier source est spécifié. Si plusieurs fichiers sources sont spécifiés, il faut absolument spécifier un répertoire destination. Dans la destination, les fichiers sont nommés avec la date en préfixe. -m, --move Déplacer le fichier SRC vers la destination DESTDIR qui vaut par défaut le répertoire courant si un seul fichier source est spécifié. Si plusieurs fichiers sources sont spécifiés, il faut absolument spécifier un répertoire destination. Dans la destination, les fichiers sont nommés avec la date en préfixe. -c, --cmd Les arguments sont une commande à lancer. Dans les argument, PLACEHOLDER est remplacé par la date. Si le PLACEHOLDER n'est trouvé dans aucun des arguments, alors ajouter la date à la fin de la commande. Par exemple, voici comment émuler l'option -k $scriptname -c cp src dest/~~ --string Remplacer dans chaque argument le placeholder par la date et afficher le résultat. -P, --placeholder PLACEHOLDER Dans le nom spécifié, remplacer PLACEHOLDER par la date. Par défaut, PLACEHOLDER vaut ~~. Si le nom spécifié ne contient pas le PLACEHOLDER, il est placé au début. -@, --force-date DATE Si une date du format attendu est déjà présente dans le nom du fichier, forcer son remplacement par la valeur spécifiée. Par défaut, le fichier n'est pas modifié si la date est déjà présente. Si le premier ou le dernier argument de ce script ressemblent à une date (ie. d/m[/y] ou @d[/m[/y]]) et qu'aucun fichier de ce nom n'existe dans le répertoire courant, activer automatiquement cette option, sauf si l'option --no-auto-force-date est spécifiée aussi. Ainsi, les commandes suivantes sont équivalentes: $scriptname -@ d/m/y file $scriptname d/m/y file $scriptname file @d/m/y -F, --format FORMAT Spécifier le format de la date à insérer dans le nom du fichier. Par défaut, FORMAT vaut 'YYMMDD-' Les formats valides sont: YYYY année sur 4 chiffres YY année sur 2 chiffres MM mois sur 2 chiffres DD jour sur 2 chiffres Tous les autres caractères sont pris tels-quels -s, --short Equivalent à -F YYMMDD --autof -l, --long Equivalent à -F YYYMMDD --autof --autof Option non (pas encore) documentée" } function create() { case "$create" in file) touch "$1";; dir) mkdir -p "$1";; esac } function have_ph() { [[ "$1" == *"$placeholder"* ]] } function replace_ph() { local fy fm fd if [ -n "$force_date" ]; then fd="${force_date:0:2}" fm="${force_date:3:2}" fy="${force_date:6:4}" fi awkrun ph="$placeholder" \ force_date="$force_date" fy:str="$fy" fm:str="$fm" fd:str="$fd" \ format="$format" autof:int="$autof" ' function short2long(s, cy, py, sy, ly) { cy = strftime("%Y") + 0 cy = cy - cy % 100 py = cy - 100 sy = substr(s, 1, 2) + 0 if (sy >= 80) ly = py + sy else ly = cy + sy return ly substr(s, 3) } BEGIN { if (format ~ /YYYYMMDD/) type = "long" else if (format ~ /YYMMDD/) type = "short" else type = "custom" if (force_date != "") { gsub(/%/, "%%", format) gsub(/YYYY/, fy, format) gsub(/YY/, substr(fy, 3, 2), format) gsub(/MM/, fm, format) gsub(/DD/, fd, format) } else { gsub(/%/, "%%", format) gsub(/YYYY/, "%Y", format) gsub(/YY/, "%y", format) gsub(/MM/, "%m", format) gsub(/DD/, "%d", format) } date = strftime(format) } { if (index($0, "/") != 0) { match($0, /\/[^/]*$/) dir = substr($0, 1, RSTART) name = substr($0, RSTART + 1) } else { dir = "" name = $0 } if (autof) { pos = index(name, ph) if (pos == 0) { if (force_date != "") { if (type == "long") { if (name ~ /^[0-9]{8}/) { name = substr(name, 9) print dir date name } else if (name ~ /^[0-9]{6}/) { name = substr(name, 7) print dir date name } else { print dir date "-" name } } else if (type == "short") { if (name ~ /^[0-9]{8}/) { name = substr(name, 9) print dir date name } else if (name ~ /^[0-9]{6}/) { name = substr(name, 7) print dir date name } else { print dir date "-" name } } else if (type == "custom") { print dir date "-" name } } else { if (type == "long") { if (name ~ /^[0-9]{8}/) print dir name else if (name ~ /^[0-9]{6}/) print dir short2long(name) else print dir date "-" name } else if (type == "short") { if (name ~ /^[0-9]{8}/) print dir substr(name, 3) else if (name ~ /^[0-9]{6}/) print dir name else print dir date "-" name } else if (type == "custom") { print dir date "-" name } } } else if (pos == 1) { print dir date "-" substr(name, length(ph) + 1) } else if (pos == length(name) - length(ph) + 1) { print dir substr(name, 1, length(name) - length(ph)) "-" date } else { print dir substr(name, 1, pos - 1) date substr(name, pos + length(ph)) } } else { pos = index(name, ph) if (pos == 0) { if (force_date != "") { if (type == "long") { if (name ~ /^[0-9]{8}/) name = substr(name, 9) print dir date name } else if (type == "short") { if (name ~ /^[0-9]{6}/) name = substr(name, 7) print dir date name } else if (type == "custom") { print dir date name } } else { if (type == "long") { if (name ~ /^[0-9]{8}/) print dir name else print dir date name } else if (type == "short") { if (name ~ /^[0-9]{6}/) print dir name else print dir date name } else if (type == "custom") { print dir date name } } } else { print dir substr(name, 1, pos - 1) date substr(name, pos + length(ph)) } } }' <<<"$1" } action=create create= case "$scriptname" in ddir) action=create; create=dir;; dfile) action=create; create=file;; dcopy) action=copy;; dmove) action=move;; dcmd) action=cmd;; esac cmd_quiet= placeholder= auto_force_date=1 force_date= format= autof= parse_opts "${PRETTYOPTS[@]}" \ --help '$exit_with display_help' \ --create-or-rename action=create \ -d,--create-dir create=dir \ -f,--create-file create=file \ -k,--copy action=copy \ -m,--move action=move \ -c,--cmd action=cmd \ --string action=string \ --cmd-quiet cmd_quiet=1 \ -P:,--placeholder: placeholder= \ --no-auto-force-date auto_force_date= \ -@:,--force-date: force_date= \ -F:,--format: format= \ -s,--short '$format=YYMMDD; autof=1' \ -l,--long '$format=YYYYMMDD; autof=1' \ --autof autof=1 \ @ args -- "$@" && set -- "${args[@]}" || die "$args" if [ -z "$force_date" -a -n "$auto_force_date" ]; then # si le premier ou le dernier argument ressemblent à une date f="$1"; f2="${f#@}" if [[ "$f" == */* ]] && [ -z "${f//[0-9\/]}" -a ! -e "$f" ]; then force_date="$f" shift elif [[ "$f" == @* ]] && [ -z "${f2//[0-9\/]}" -a ! -e "$f2" ]; then force_date="$f2" shift elif [ $# -gt 1 ]; then l="${@:$#}"; l2="${l#@}" if [[ "$l" == */* ]] && [ -z "${l//[0-9\/]}" -a ! -e "$l" ]; then force_date="$l" set -- "${@:1:$(($# - 1))}" elif [[ "$l" == @* ]] && [ -z "${l2//[0-9\/]}" -a ! -e "$l2" ]; then force_date="$l2" set -- "${@:1:$(($# - 1))}" fi fi fi [ -n "$create" ] || create=file [ -n "$placeholder" ] || placeholder="~~" [ -n "$force_date" ] && setx force_date=parse_date "$force_date" if [ -z "$format" ]; then format=YYMMDD autof=1 fi if [ "$action" == cmd ]; then # Il faut lancer une commande spécifiée [ $# -gt 0 ] || set -- echo args=() found= for arg in "$@"; do if have_ph "$arg"; then [ -z "$cmd_quiet" ] && check_interaction -c && evalx qvals "${args[@]}" "$arg" // estepi "Commande:" setx arg=replace_ph "$arg" "$force_date" read_value "Veuillez confirmer le nom" arg "$arg" found=1 fi args=("${args[@]}" "$arg") done if [ -z "$found" ]; then setx arg=replace_ph "" "$force_date" read_value "Veuillez entrer le nom du fichier" arg "$arg" args=("${args[@]}" "$arg") fi if show_debug; then evalx qvals "${args[@]}" // edebug "Commande effective:" ask_yesno "Voulez-vous continuer?" X || die fi "${args[@]}" elif [ "$action" == copy -o "$action" == move ]; then if [ $# -eq 0 ]; then die "Vous devez spécifier les fichiers" elif [ $# -eq 1 ]; then src="$1" destdir=. srcs=("$src") else args=("$@") setx destdir=last_value args array_copy_firsts srcs args fi if [ ! -d "$destdir" ]; then ewarn "$destdir: répertoire introuvable" ask_yesno "Voulez-vous le créer?" X || die mkdir -p "$destdir" || die fi if [ "$action" == copy ]; then cmdinfo="Copie" cmd=(cp -i) elif [ "$action" == move ]; then cmdinfo="Déplacement" cmd=(mv -i) fi for src in "${srcs[@]}"; do setx src=abspath "$src" setx srcname=basename -- "$src" if [ -e "$src" ]; then estep "$cmdinfo de $(ppath "$src")" setx destname=replace_ph "$srcname" "$force_date" setx dest=abspath "$destdir/$destname" [ "$src" != "$dest" ] || ewarn "La source et la destination sont identiques" read_value "Veuillez confirmer le nom" destname "$destname" setx dest=abspath "$destdir/$destname" [ "$src" != "$dest" ] && "${cmd[@]}" "$src" "$destdir/$destname" else ewarn "$src: fichier introuvable" fi done elif [ "$action" == create ]; then if [ $# -gt 0 ]; then for src in "$@"; do setx src=abspath "$src" setx dir=dirname -- "$src" setx srcname=basename -- "$src" if [ -e "$src" ]; then setx destname=replace_ph "$srcname" "$force_date" setx dest=abspath "$dir/$destname" confirm_do=1 if [ "$src" == "$dest" ]; then if [ -n "$force_date" ]; then ewarn "La source et la destination sont identiques" else estepi "$(ppath "$src"): aucun renommage nécessaire" confirm_do= fi fi if [ -n "$confirm_do" ]; then estep "Renommage de $(ppath "$src")" read_value "Veuillez confirmer le nom" destname "$destname" setx dest=abspath "$dir/$destname" [ "$src" != "$dest" ] && mv -i "$src" "$dir/$destname" fi else setx destname=replace_ph "$srcname" "$force_date" setx dest=abspath "$dir/$destname" if [ -d "$dest" ]; then ewarn "$srcname --> $(ppath "$dest"): répertoire existant" elif [ -e "$dest" ]; then ewarn "$srcname --> $(ppath "$dest"): fichier existant" else estep "$srcname --> Création de $(ppath "$dest")" fi read_value "Veuillez confirmer le nom" destname "$destname" setx dest=abspath "$dir/$destname" create "$dir/$destname" fi done else setx destname=replace_ph "" "$force_date" confirm_action=entrer if [ -d "$destname" ]; then ewarn "$destname: répertoire existant" confirm_action=confirmer elif [ -e "$destname" ]; then ewarn "$destname: fichier existant" confirm_action=confirmer else case "$create" in file) estep "Création d'un nouveau fichier";; dir) estep "Création d'un nouveau répertoire";; esac fi read_value "Veuillez $confirm_action le nom" destname "$destname" create "$destname" fi elif [ "$action" == string ]; then if [ $# -gt 0 ]; then for string in "$@"; do replace_ph "$string" "$force_date" done else replace_ph "" "$force_date" fi else die "$action: action non implémentée" fi