305 lines
9.4 KiB
Bash
305 lines
9.4 KiB
Bash
# -*- 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
|
|
}
|