431 lines
		
	
	
		
			14 KiB
		
	
	
	
		
			Bash
		
	
	
		
			Executable File
		
	
	
	
	
			
		
		
	
	
			431 lines
		
	
	
		
			14 KiB
		
	
	
	
		
			Bash
		
	
	
		
			Executable File
		
	
	
	
	
| #!/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/ulib" || exit 1
 | |
| urequire DEFAULTS
 | |
| 
 | |
| 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
 |