# -*- coding: utf-8 mode: sh -*- vim:sw=4:sts=4:et:ai:si:sta:fenc=utf-8 ##@cooked nocomments module: base.path "Fonctions de base: gestion des chemins et des fichiers" function: in_path "tester l'existence d'un programme dans le PATH" function in_path() { [ -n "$1" -a -x "$(which "$1" 2>/dev/null)" ] } function: delpath "supprimer le chemin \$1 de \$2(=PATH)" function delpath() { local _qdir="${1//\//\\/}" eval "export ${2:-PATH}; ${2:-PATH}"'="${'"${2:-PATH}"'#$1:}"; '"${2:-PATH}"'="${'"${2:-PATH}"'%:$1}"; '"${2:-PATH}"'="${'"${2:-PATH}"'//:$_qdir:/:}"; [ "$'"${2:-PATH}"'" == "$1" ] && '"${2:-PATH}"'=' } function: addpath "Ajouter le chemin \$1 à la fin, dans \$2(=PATH), s'il n'y existe pas déjà" function addpath() { local _qdir="${1//\//\\/}" eval "export ${2:-PATH}; "'[ "${'"${2:-PATH}"'#$1:}" == "$'"${2:-PATH}"'" -a "${'"${2:-PATH}"'%:$1}" == "$'"${2:-PATH}"'" -a "${'"${2:-PATH}"'//:$_qdir:/:}" == "$'"${2:-PATH}"'" -a "$'"${2:-PATH}"'" != "$1" ] && '"${2:-PATH}"'="${'"${2:-PATH}"':+$'"${2:-PATH}"':}$1"' } function: inspathm "Ajouter le chemin \$1 au début, dans \$2(=PATH), s'il n'y existe pas déjà" function inspathm() { local _qdir="${1//\//\\/}" eval "export ${2:-PATH}; "'[ "${'"${2:-PATH}"'#$1:}" == "$'"${2:-PATH}"'" -a "${'"${2:-PATH}"'%:$1}" == "$'"${2:-PATH}"'" -a "${'"${2:-PATH}"'//:$_qdir:/:}" == "$'"${2:-PATH}"'" -a "$'"${2:-PATH}"'" != "$1" ] && '"${2:-PATH}"'="$1${'"${2:-PATH}"':+:$'"${2:-PATH}"'}"' } function: inspath "S'assurer que le chemin \$1 est au début de \$2(=PATH)" function inspath() { delpath "$@" inspathm "$@" } function: push_cwd "enregistrer le répertoire courant dans la variable \$2(=cwd) et se placer dans le répertoire \$1" function push_cwd() { eval "${2:-cwd}"'="$(pwd)"' cd "$1" } function: pop_cwd "se placer dans le répertoire \${!\$2}(=\$cwd) puis retourner le code d'erreur \$1(=0)" function pop_cwd() { eval 'cd "$'"${2:-cwd}"'"' return "${1:-0}" } ################################################################################ ## fichiers temporaires function: mktempf "générer un fichier temporaire et retourner son nom" function mktempf() { mktemp "${1:-"$TMPDIR/tmp.XXXXXX"}" } function: mktempd "générer un répertoire temporaire et retourner son nom" function mktempd() { mktemp -d "${1:-"$TMPDIR/tmp.XXXXXX"}" } function ac__forgetall() { NULIB__AC_FILES=(); } ac__forgetall function ac__trap() { local file for file in "${NULIB__AC_FILES[@]}"; do [ -e "$file" ] && rm -rf "$file" 2>/dev/null done ac__forgetall } trap ac__trap 1 3 15 EXIT function: autoclean "\ Ajouter les fichiers spécifiés à la liste des fichiers à supprimer à la fin du programme" function autoclean() { local file for file in "$@"; do [ -n "$file" ] && NULIB__AC_FILES=("${NULIB__AC_FILES[@]}" "$file") done } function: ac_cleanall "\ Supprimer *tous* les fichiers temporaires gérés par autoclean tout de suite." function ac_cleanall() { ac__trap } function: ac_clean "\ Supprimer les fichier temporaires \$1..@ si et seulement s'ils ont été générés par ac_set_tmpfile() ou ac_set_tmpdir()" function ac_clean() { local file acfile found local -a acfiles for acfile in "${NULIB__AC_FILES[@]}"; do found= for file in "$@"; do if [ "$file" == "$acfile" ]; then found=1 [ -e "$file" ] && rm -rf "$file" 2>/dev/null break fi done [ -z "$found" ] && acfiles=("${acfiles[@]}" "$acfile") done NULIB__AC_FILES=("${acfiles[@]}") } function: ac_set_tmpfile "\ Créer un fichier temporaire avec le motif \$2, l'ajouter à la liste des fichiers à supprimer en fin de programme, et mettre sa valeur dans la variable \$1 En mode debug, si (\$5 est vide ou \${!5} est une valeur vraie), et si \$3 n'est pas vide, prendre ce fichier au lieu de générer un nouveau fichier temporaire. Si \$4==keep, ne pas écraser le fichier \$3 s'il existe." function ac_set_tmpfile() { local se__d if is_debug; then if [ -n "$5" ]; then is_yes "${!5}" && se__d=1 else se__d=1 fi fi if [ -n "$se__d" -a -n "$3" ]; then _setv "$1" "$3" [ -f "$3" -a "$4" == keep ] || >"$3" else local se__t="$(mktempf "$2")" autoclean "$se__t" _setv "$1" "$se__t" fi } function: ac_set_tmpdir "\ Créer un répertoire temporaire avec le motif \$2, l'ajouter à la liste des fichiers à supprimer en fin de programme, et mettre sa valeur dans la variable \$1 En mode debug, si (\$4 est vide ou \${!4} est une valeur vraie), et si \$3 n'est pas vide, prendre ce nom de répertoire au lieu de créer un nouveau répertoire temporaire" function ac_set_tmpdir() { local sr__d if is_debug; then if [ -n "$4" ]; then is_yes "${!4}" && sr__d=1 else sr__d=1 fi fi if [ -n "$sr__d" -a -n "$3" ]; then _setv "$1" "$3" mkdir -p "$3" else local sr__t="$(mktempd "$2")" autoclean "$sr__t" _setv "$1" "$sr__t" fi } ################################################################################ ## manipulation de chemins #XXX repris tel quel depuis nutools, à migrer function normpath() { # normaliser le chemin $1, qui est soit absolu, soit relatif à $2 (qui vaut # $(pwd) par défaut) local -a parts local part ap IFS=/ read -a parts <<<"$1" if [ "${1#/}" != "$1" ]; then ap=/ elif [ -n "$2" ]; then ap="$2" else ap="$(pwd)" fi for part in "${parts[@]}"; do if [ "$part" == "." ]; then continue elif [ "$part" == ".." ]; then ap="${ap%/*}" [ -n "$ap" ] || ap=/ else [ "$ap" != "/" ] && ap="$ap/" ap="$ap$part" fi done echo "$ap" } function __normpath() { # normaliser dans les cas simple le chemin absolu $1. sinon retourner 1. # cette fonction est utilisée par abspath() if [ -d "$1" ]; then if [ -x "$1" ]; then # le cas le plus simple: un répertoire dans lequel on peut entrer (cd "$1"; pwd) return 0 fi elif [ -f "$1" ]; then local dn="$(dirname -- "$1")" bn="$(basename -- "$1")" if [ -x "$dn" ]; then # autre cas simple: un fichier situé dans un répertoire dans lequel # on peut entrer (cd "$dn"; echo "$(pwd)/$bn") return 0 fi fi return 1 } function abspath() { # Retourner un chemin absolu vers $1. Si $2 est non nul et si $1 est un chemin # relatif, alors $1 est exprimé par rapport à $2, sinon il est exprimé par # rapport au répertoire courant. # Si le chemin n'existe pas, il n'est PAS normalisé. Sinon, les meilleurs # efforts sont faits pour normaliser le chemin. local ap="$1" if [ "${ap#/}" != "$ap" ]; then # chemin absolu. on peut ignorer $2 __normpath "$ap" && return else # chemin relatif. il faut exprimer le chemin par rapport à $2 local cwd if [ -n "$2" ]; then cwd="$(abspath "$2")" else cwd="$(pwd)" fi ap="$cwd/$ap" __normpath "$ap" && return fi # dans les cas spéciaux, il faut calculer "manuellement" le répertoire absolu normpath "$ap" } function ppath() { # Dans un chemin *absolu*, remplacer "$HOME" par "~" et "$(pwd)/" par "", afin # que le chemin soit plus facile à lire. Le répertoire courant est spécifié par # $2 ou $(pwd) si $2 est vide local path="$1" cwd="$2" path="$(abspath "$path")" # essayer de normaliser le chemin [ -n "$cwd" ] || cwd="$(pwd)" [ "$path" == "$cwd" ] && path="." [ "$cwd" != "/" -a "$cwd" != "$HOME" ] && path="${path#$cwd/}" [ "${path#$HOME/}" != "$path" ] && path="~${path#$HOME}" echo "$path" } function ppath2() { # Comme ppath() mais afficher '.' comme '. ($dirname)' pour la joliesse local path="$1" cwd="$2" path="$(abspath "$path")" # essayer de normaliser le chemin [ -n "$cwd" ] || cwd="$(pwd)" if [ "$path" == "$cwd" ]; then path=". ($(basename -- "$path"))" else [ "$cwd" != "/" -a "$cwd" != "$HOME" ] && path="${path#$cwd/}" [ "${path#$HOME/}" != "$path" ] && path="~${path#$HOME}" fi echo "$path" } function relpath() { # Afficher le chemin relatif de $1 par rapport à $2. Si $2 n'est pas spécifié, # on prend le répertoire courant. Si $1 ou $2 ne sont pas des chemins absolus, # il sont transformés en chemins absolus par rapport à $3. Si $1==$2, retourner # une chaine vide local p="$(abspath "$1" "$3")" cwd="$2" if [ -z "$cwd" ]; then cwd="$(pwd)" else cwd="$(abspath "$cwd" "$3")" fi if [ "$p" == "$cwd" ]; then echo "" elif [ "${p#$cwd/}" != "$p" ]; then echo "${p#$cwd/}" else local rp while [ -n "$cwd" -a "${p#$cwd/}" == "$p" ]; do rp="${rp:+$rp/}.." cwd="${cwd%/*}" done rp="$rp/${p#$cwd/}" # ${rp%//} traite le cas $1==/ echo "${rp%//}" fi } function relpathx() { # Comme relpath, mais pour un chemin vers un exécutable qu'il faut lancer: # s'assurer qu'il y a une spécification de chemin, e.g. ./script local p="$(relpath "$@")" if [ -z "$p" ]; then echo . elif [ "${p#../}" != "$p" -o "${p#./}" != "$p" ]; then echo "$p" else echo "./$p" fi }