fnconv accepte une liste de commandes

This commit is contained in:
Jephte CLAIN 2014-10-12 22:54:49 +04:00
parent d8453b3d84
commit 1fccb5a900
1 changed files with 225 additions and 88 deletions

313
fnconv
View File

@ -1,100 +1,237 @@
#!/bin/bash
# -*- coding: utf-8 mode: sh -*- vim:sw=4:sts=4:et:ai:si:sta:fenc=utf-8
function display_help() {
uecho "$scriptname: renommer des fichiers en changeant leur encoding
USAGE
$scriptname [-f src_enc] [ -t dest_enc] [/path/to/file]
OPTIONS
-f from
Encoding source. Si n'est pas spécifié ou vaut 'detect', l'encoding est
autodétecté.
-t to
Encoding destination. Doit être spécifié.
-N Ne pas optimiser le calcul de l'encoding. Cette option n'est valide que
si -f n'est pas spécifié. On assume que tous les noms de fichiers n'ont
pas le même encoding. L'encoding from est donc recalculé à chaque fois.
-r inverser from et to, qui doivent être tous les deux spécifiés."
}
if [ "$#" -eq 1 -a "$1" == --nutools-makelinks ]; then
# créer les liens
scriptname="$(basename "$0")"
for destenc in latin1 utf8; do
ln -s "$scriptname" "${scriptname}2$destenc"
done
exit 0
fi
source "$(dirname "$0")/lib/ulib/ulib" || exit 1
urequire DEFAULTS
from=detect
case "${scriptname#fnconv2}" in
utf8) to=utf-8;;
latin1) to=iso-8859-1;;
*) to=;;
esac
optimize=1
parse_opts "${PRETTYOPTS[@]}" \
--help '$exit_with display_help' \
-f: from= \
-t: to= \
-N optimize= \
-r reverse \
@ args -- "$@" && set -- "${args[@]}" || die "$args"
function display_help() {
uecho "$scriptname: renommer un fichier ou les fichiers d'un répertoire
function fnconv() {
# $1 = fichier à renommer
local lfrom="$from" lto="$to"
local srcdir="$(dirname "$1")"
local srcname="$(basename "$1")"
if [ "$lfrom" == "detect" ]; then
lfrom="$("$scriptdir/lib/pywrapper" uencdetect.py "$srcname")"
if [ "$lfrom" == "Unknown" ]; then
eerror "$srcname: Impossible de déterminer l'encoding"
return 1
fi
if [ -n "$optimize" ]; then
from="$(__norm_encoding "$lfrom")"
[ "$from" != "$to" ] && enote "Conversion $from --> $to"
fi
fi
if [ -n "$optimize" -a "$from" == "$to" ]; then
die "Une conversion de $from à $to n'a pas de sens.
Veuillez re-essayer avec -N si nécessaire."
fi
USAGE
$scriptname [options] <file|dir> [cmds...]
if [ -n "$reverse" ]; then
tmp="$lto"
lto="$lfrom"
lfrom="$tmp"
fi
Une ou plusieurs commandes peuvent être spécifiées, séparées //
La commande par défaut est 'fixcase'
local src="$(abspath "$srcdir/$srcname")"
local dest
dest="$srcdir/$(iconv -f "$lfrom" -t "$lto" <<<"$srcname")" || return 1
dest="$(abspath "$dest")"
if [ "$src" != "$dest" ]; then
ebegin "$(ppath "$src") --> $(basename "$dest")" \
mv "$src" "$dest"
fi
src="$dest"
if [ -d "$src" ]; then
etitle -s "$(ppath "$src")"
local subsrcs subsrc
array_lsall subsrcs "$src"
for subsrc in "${subsrcs[@]}"; do
fnconv "$subsrc"
done
eend
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.
COMMANDES
conv dest_enc [src_enc]
Convertir le nom du 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é.
utf8 [src_enc]
Equivalent à conv utf8 src_enc
latin1 [src_enc]
Equivalent à conv latin1 src_enc
noaccents
Transformer les caractères accentués en caractères non accentués
lowercase
Transfomer le nom en minuscule
uppercase
Transformer le nom en majuscule
fixcase
Transformer le nom en minuscule s'il est entièrement en majuscule"
}
function _lowercase() {
evalx cat // strlower
}
function _uppercase() {
evalx cat // strupper
}
function _fixcase() {
local actual upper
setx actual=cat
setx upper=strupper "$actual"
if [ "$actual" == "$upper" ]; then
strlower "$actual"
else
echo "$actual"
fi
}
[ -n "$to" ] || die "Il faut spécifier l'encoding de destination"
to="$(__norm_encoding "$to")"
for src in "$@"; do
fnconv "$src"
function detect_enc() {
local filename enc
if [ -f "$1" ]; then
setx filename=basename -- "$1"
elif [ -d "$1" ]; then
local -a files
setx -a files=evalp find "$1" // head -n1
if [ ${#files[*]} -gt 0 ]; then
setx filename=basename -- "${files[0]}"
fi
fi
setx enc="$scriptdir/lib/pywrapper" uencdetect.py "$filename"
echo "$enc"
[ "$enc" != Unknown ]
}
function before_parse_cmd() {
case "$1" in
conv)
if [ -n "$OPTIMIZE_CONV" ]; then
local to="$2"
[ -n "$to" ] && setx CONV_TO=__norm_encoding "$to"
local from="${3:-detect}"
if [ "$from" == "detect" ]; then
setx from=detect_enc "$FILE"
if [ "$from" == "Unknown" ]; 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) parse_cmd conv utf8 "$@";;
latin1) parse_cmd conv latin1 "$@";;
conv)
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
;;
noaccents|noa|fixchars) echo _noaccents;;
lowercase|lower|l) echo _lowercase;;
uppercase|upper|U) echo _uppercase;;
fixcase|fix|c) echo _fixcase;;
*)
echo "$cmd: commande invalide"
return 1
;;
esac
return 0
}
function fnconv() {
local dir oldname newname
setx dir=dirname -- "$FILE"
setx oldname=basename -- "$FILE"
setx newname=eval "$CMD" <<<"$oldname"
if [ -d "$FILE" ]; then
if [ "$newname" != "$oldname" ]; then
etitle "$(ppath "$FILE") --> $newname"
mv "$FILE" "$dir/$newname" || die
FILE="$dir/$newname"
else
etitle "$(ppath "$FILE")"
fi
local -a sfiles
array_lsall sfiles "$FILE"
for FILE in "${sfiles[@]}"; do
fnconv
done
eend
else
if [ "$newname" != "$oldname" ]; then
estep "$oldname --> $newname"
mv "$FILE" "$dir/$newname" || die
FILE="$dir/$newname"
fi
fi
}
OPTIMIZE_CONV=1
REVERSE_CONV=
CONV_FROM=
CONV_TO=
parse_opts "${PRETTYOPTS[@]}" \
--help '$exit_with display_help' \
-N,--detect-always OPTIMIZE_CONV= \
-r,--reverse REVERSE_CONV=1 \
@ args -- "$@" && set -- "${args[@]}" || die "$args"
FILE="$1"; shift
[ "$FILE" == - ] && FILE=/dev/stdin
if [ "$FILE" != /dev/stdin ]; then
[ -e "$FILE" ] || die "$FILE: fichier introuvable"
fi
[ $# -gt 0 ] || set -- fixcase # 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"
CMD="${CMD:+$CMD | }$cmd"
fi
done
if [ "$FILE" == /dev/stdin ]; then
eval "$CMD"
elif [ -f "$FILE" -o -d "$FILE" ]; then
fnconv
else
die "$FILE: fichier invalide"
fi