245 lines
		
	
	
		
			7.1 KiB
		
	
	
	
		
			Bash
		
	
	
		
			Executable File
		
	
	
	
	
			
		
		
	
	
			245 lines
		
	
	
		
			7.1 KiB
		
	
	
	
		
			Bash
		
	
	
		
			Executable File
		
	
	
	
	
| #!/bin/bash
 | |
| # -*- coding: utf-8 mode: sh -*- vim:sw=4:sts=4:et:ai:si:sta:fenc=utf-8
 | |
| source "$(dirname -- "$0")/lib/ulib/auto" || exit 1
 | |
| 
 | |
| function display_help() {
 | |
|     uecho "$scriptname: convertir un fichier ou les fichiers d'un répertoire
 | |
| 
 | |
| USAGE
 | |
|     $scriptname -f FILE [cmds...]
 | |
|     $scriptname FILE [cmds...]
 | |
| 
 | |
| Une ou plusieurs commandes peuvent être spécifiées, séparées par //
 | |
| La commande par défaut est 'lf'
 | |
| Si des commandes utilisant des options sont utilisées, penser à séparer les
 | |
| options de $scriptname avec --
 | |
| 
 | |
| OPTIONS
 | |
|     -N, --detect-always
 | |
|         Pour la commande conv, ne pas optimiser le calcul de l'encoding. Cette
 | |
|         option n'est valide que si src_enc n'est pas spécifié. On assume que
 | |
|         tous les fichiers n'ont pas le même encoding: l'encoding src_enc est
 | |
|         donc recalculé à chaque fois.
 | |
|     -r, --reverse
 | |
|         Pour la commande conv, inverser src_enc et dest_enc, qui doivent être
 | |
|         tous les deux spécifiés.
 | |
|     -f, --file FILE
 | |
|         Spécifier le fichier ou le répertoire concerné par la conversion. Les
 | |
|         aliases -d et --dir sont aussi reconnus.
 | |
|         Si cette option n'est pas spécifiée, le premier argument est considéré
 | |
|         comme le nom du fichier ou du répertoire à convertir. Par défaut,
 | |
|         convertir l'entrée standard.
 | |
|         Si un répertoire est spécifié, tous les fichiers de ce répertoire et de
 | |
|         ses sous-répertoires sont recherchés de façon récursive, sans limite de
 | |
|         profondeur. Ensuite, chacun de ces fichiers est converti.
 | |
|     --show-cmd
 | |
|         Afficher la commande qui serait exécutée
 | |
| 
 | |
| COMMANDES
 | |
|     c, conv dest_enc [src_enc]
 | |
|         Convertir le fichier dans un autre encoding.
 | |
|         dest_enc est l'encoding destination. Il doit être spécifié.
 | |
|         src_enc est l'encoding source. S'il n'est pas spécifié ou vaut 'detect',
 | |
|             il est autodétecté.
 | |
|     U, utf8 [src_enc]
 | |
|         Equivalent à conv utf8 src_enc
 | |
|     L, latin1 [src_enc]
 | |
|         Equivalent à conv latin1 src_enc
 | |
|     lf
 | |
|     crlf
 | |
|     cr
 | |
|         Convertir respectivement les caractères de fin de ligne en LF, CR/LF ou CR
 | |
|     lc, latin1compat
 | |
|         Transformer certains caratères UTF-8 en équivalents qui existent en Latin1
 | |
|     na, noaccents
 | |
|         Transformer les caractères accentués en caractères non accentués
 | |
|     [sed] s/from/to/opts
 | |
|         Filtrer avec l'expression régulière de sed 's/from/to/opts'
 | |
|     sort [-u]
 | |
|         Trier le fichier avec la commande sort. Attention! Il ne faut utiliser
 | |
|         que les options de sort qui agissent sur un flux e.g. -u pour trier les
 | |
|         lignes de façon unique."
 | |
| }
 | |
| 
 | |
| function detect_enc() {
 | |
|     local enc
 | |
|     if [ -f "$1" ]; then
 | |
|         setx enc="$scriptdir/lib/pywrapper" uencdetect.py -f "$1"
 | |
|     elif [ -d "$1" ]; then
 | |
|         local -a files
 | |
|         setx -a files=evalp find "$1" -type f // head -n1
 | |
|         if [ ${#files[*]} -gt 0 ]; then
 | |
|             setx enc="$scriptdir/lib/pywrapper" uencdetect.py -f "${files[0]}"
 | |
|         fi
 | |
|     fi
 | |
|     [ -n "$enc" ] || enc=Unknown
 | |
|     echo "$enc"
 | |
|     [ "$enc" != Unknown ]
 | |
| }
 | |
| 
 | |
| function before_parse_cmd() {
 | |
|     case "$1" in
 | |
|     conv|c)
 | |
|         if [ -n "$OPTIMIZE_CONV" ]; then
 | |
|             local to="$2"
 | |
|             [ -n "$to" ] && setx CONV_TO=__norm_encoding "$to"
 | |
| 
 | |
|             local from="${3:-detect}"
 | |
|             if [ "$from" == "detect" ]; then
 | |
|                 if ! setx from=detect_enc "$FILE"; then
 | |
|                     echo "$FILE: Impossible de détecter l'encoding"
 | |
|                     return 1
 | |
|                 fi
 | |
|             fi
 | |
|             [ -n "$from" ] && setx CONV_FROM=__norm_encoding "$from"
 | |
|             OPTIMIZE_CONV=
 | |
|         fi
 | |
|         ;;
 | |
|     esac
 | |
| }
 | |
| 
 | |
| function iconv_detect() {
 | |
|     local to="$1"; shift
 | |
|     local from
 | |
|     if setx from=detect_enc "$FILE"; then
 | |
|         if [ -n "$REVERSE_CONV" ]; then
 | |
|             local tmp="$to"
 | |
|             to="$from"
 | |
|             from="$tmp"
 | |
|         fi
 | |
|         iconv -f "$from" -t "$to" "$@"
 | |
|         return 0
 | |
|     else
 | |
|         cat
 | |
|         return 1
 | |
|     fi
 | |
| }
 | |
| 
 | |
| function parse_cmd() {
 | |
|     local cmd="$1"; shift
 | |
|     local -a args
 | |
|     case "$cmd" in
 | |
|     utf8|U) parse_cmd conv utf8 "$@";;
 | |
|     latin1|L) parse_cmd conv latin1 "$@";;
 | |
|     conv|c)
 | |
|         local to="$CONV_TO" from="$CONV_FROM"
 | |
|         [ -n "$to" ] || to="$1"; shift
 | |
|         [ -f "$from" ] || from="${1:-detect}"; shift
 | |
| 
 | |
|         if [ -z "$to" ]; then
 | |
|             echo "conv: vous devez spécifier l'encoding destination"
 | |
|             return 1
 | |
|         fi
 | |
|         setx to=__norm_encoding "$to"
 | |
|         if [ "$from" == "detect" ]; then
 | |
|             qvals iconv_detect "$to" "$@"
 | |
|         else
 | |
|             setx from=__norm_encoding "$from"
 | |
|             if [ "$from" == "$to" ]; then
 | |
|                 echo "Une conversion de $from à $to n'a pas de sens. Veuillez re-essayer avec -N si nécessaire."
 | |
|                 return 1
 | |
|             fi
 | |
|             if [ -n "$REVERSE_CONV" ]; then
 | |
|                 local tmp="$to"
 | |
|                 to="$from"
 | |
|                 from="$tmp"
 | |
|             fi
 | |
|             qvals iconv -f "$from" -t "$to" "$@"
 | |
|         fi
 | |
|         ;;
 | |
|     lf) echo _nl2lf;;
 | |
|     crlf) echo _nl2crlf;;
 | |
|     cr) echo _nl2cr;;
 | |
|     latin1compat|lc) echo _latin1compat;;
 | |
|     noaccents|na|fixchars|fc) echo _noaccents;;
 | |
|     s/*) qvals sed "$cmd" "$@";;
 | |
|     sed) qvals sed "$@";;
 | |
|     sort) qvals sort "$@";;
 | |
|     *)
 | |
|         echo "$cmd: commande invalide"
 | |
|         return 1
 | |
|         ;;
 | |
|     esac
 | |
|     return 0
 | |
| }
 | |
| 
 | |
| function ffconv() {
 | |
|     local tmp="$FILE.tmp.$$"
 | |
|     autoclean "$tmp"
 | |
| 
 | |
|     ebegin "$FILE"
 | |
|     if eval "$CMD" <"$FILE" >"$tmp"; then
 | |
|         (cat "$tmp" >"$FILE"; edot $? "replace $FILE")
 | |
|     fi
 | |
|     (rm "$tmp"; edot $? "remove temp")
 | |
|     eend
 | |
| }
 | |
| 
 | |
| CONV_FROM=
 | |
| CONV_TO=
 | |
| OPTIMIZE_CONV=1
 | |
| REVERSE_CONV=
 | |
| FILE=
 | |
| show_cmd=
 | |
| parse_opts "${PRETTYOPTS[@]}" \
 | |
|     --help '$exit_with display_help' \
 | |
|     -N,--detect-always OPTIMIZE_CONV= \
 | |
|     -r,--reverse REVERSE_CONV=1 \
 | |
|     -f:,--file:,-d:,--dir: FILE= \
 | |
|     --show-cmd show_cmd=1 \
 | |
|     @ args -- "$@" && set -- "${args[@]}" || die "$args"
 | |
| 
 | |
| if [ -z "$FILE" ]; then
 | |
|     FILE="${1:--}"
 | |
|     shift
 | |
| fi
 | |
| [ "$FILE" == - ] && FILE=/dev/stdin
 | |
| if [ "$FILE" != /dev/stdin ]; then
 | |
|     [ -e "$FILE" ] || die "$FILE: fichier introuvable"
 | |
| fi
 | |
| 
 | |
| [ $# -gt 0 ] || set -- lf # commande par défaut
 | |
| 
 | |
| CMD= # la commande finale à lancer pour convertir le flux
 | |
| while [ $# -gt 0 ]; do
 | |
|     args=()
 | |
|     while [ $# -gt 0 ]; do
 | |
|         arg="$1"; shift
 | |
|         if [ "$arg" == // ]; then
 | |
|             break
 | |
|         elif [ "${arg%//}" != "$arg" ]; then
 | |
|             local tmp="${arg%//}"
 | |
|             if [ -z "${tmp//\\/}" ]; then
 | |
|                 arg="${arg#\\}"
 | |
|             fi
 | |
|         fi
 | |
|         args=("${args[@]}" "$arg")
 | |
|     done
 | |
| 
 | |
|     if [ ${#args[*]} -gt 0 ]; then
 | |
|         before_parse_cmd "${args[@]}"
 | |
|         setx cmd=parse_cmd "${args[@]}" || die "$cmd"
 | |
|         if [ "$FILE" == /dev/stdin ]; then
 | |
|             # pas de suivi pour /dev/stdin
 | |
|             CMD="${CMD:+$CMD | }$cmd"
 | |
|         else
 | |
|             CMD="${CMD:+$CMD | }($cmd; edot \$? $cmd)"
 | |
|         fi
 | |
|     fi
 | |
| done
 | |
| 
 | |
| if [ -n "$show_cmd" ]; then
 | |
|     echo "$CMD"
 | |
| elif [ "$FILE" == /dev/stdin ]; then
 | |
|     eval "$CMD"
 | |
| elif [ -f "$FILE" ]; then
 | |
|     ffconv
 | |
| elif [ -d "$FILE" ]; then
 | |
|     setx -a files=find "$FILE" -type f
 | |
|     for FILE in "${files[@]}"; do
 | |
| 	ffconv
 | |
|     done
 | |
| else
 | |
|     die "$FILE: fichier invalide"
 | |
| fi
 |