#!/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