Chemin absolu et relatif

 

chemin absolu et relatif

OCZ(16 juillet 2004) : La designation d'un chemin peut devenir complexe et volubile, comme par exemple :

    cd /home/chezmoi/../chezlui/aaa/bb/../yy

Ceci pour designer plus simplement ce chemin par :

    cd  /home/chezlui/aaa/yy

La compression est d'autant plus interessante surtout pendant la construction d'une seule ligne contenant tous les chemins des fichiers necessaires a la confection d'un travail.On obtient par surprise ce doux message du systeme word too long ... et donc comprimons si nous pouvons et ceci de maniere automatique, bien sur !.

La compression ou la minimisation de la longueur d'adressage peut se faire suivant 2 methodes :


ulis: dommage de dupliquer une fonction existante car abspath peut être remplacé par : set npath [file normalize path].

relpath, par contre peut s'avérer utile, mais gagnerait à utiliser file normalize.


abspath

Description de la fonction abspath qui retourne le nom complet du repertoire designe

 #
 # =======================================================
 #  ABSPATH : retourne le nom complet du repertoire
 #            designe en position relative ou non
 #            abspath "/o/c/g/../z" ===>  /o/c/z
 #  par      : Jacques.Oczkowski
 #  courriel : ocz@lcpc.fr
 # =======================================================
 proc abspath { dirpath } {
  set l [file split $dirpath]
  set p [lsearch $l ..]
  # === il n'y a pas de .. dans dirpath
  if {$p == -1} { return $dirpath}
  # === le debut commence par ..
  if {$p == 0 } {
   set l [file split [file join [pwd] $dirpath]]
   set p [lsearch $l ..]
  }
  # === traitement
  while {$p != -1} {
    set l "[lreplace $l [expr {$p - 1}] end ] [lreplace $l 0 $p ]"
    set p [lsearch $l ..]
  }
  # === solution generale
  set newpath ""
  foreach mm $l { set newpath [file join $newpath $mm ]}
  return $newpath
 }

relapath

Description de la fonction relapath qui retourne le nom relatif du repertoire designe

 # =======================================================
 #  RELAPARH : retourne le chemin relatif par comparaison
 #             entre le PWD et le chemin absolu designe
 #  par      : Jacques.Oczkowski
 #  courriel : ocz@lcpc.fr
 # =======================================================
 proc relapath { dirpath } {
  # === controle de dirpath
  if { [lsearch [file split $dirpath] ..] != -1} {
   return "\n erreur relapath : $dirpath \
           \n le repertoire doit etre designe en absolu \n"
  #  exit
  }
  #
  set maposi [pwd]
  # === dirpath et pwd sont identiques
  if {[string compare $dirpath $maposi] == 0} {return .}
  # === traitement
  set l1 [file split $maposi]
  set l2 [file split $dirpath]
  set np ""
  foreach k $l1 {
     if {[lsearch $l2 $k] == -1 } {
        lappend np ..
     } else {
        set i2 [lsearch $l2 $k]
     }
  }
  # === dirpath et pwd totalement different ,alors dirpath est la solution
  if {[lsearch $l1 [lindex $l1 end]] == [llength $np]} {return $dirpath}
  # === solution generale
  set rela  "$np [lreplace $l2 0 $i2 ]"
  set newpath ""
  foreach mm $rela { set newpath [file join $newpath $mm ]}
  return $newpath
 }

Exemple d'utilisation de ces fonctions sous UNIX et WINDOWS :


 #!/bin/sh
 # the next line restarts using wish \
 exec tclsh "$0" "$@"
 source abspath.tcl
 source relapath.tcl
 #
 global tcl_platform
 #  SYSTEME UNIX
    if {$tcl_platform(platform) == "unix"} {
 puts " ======= fonction ABSPATH\n"
 #
 puts "[abspath /udd/lpmn/ocz]"
 puts "[abspath "/o/c/g/../z"]"
 puts "[abspath /a/b/f/..]"
 puts "[abspath ../d/k/r]"

 puts " ======= fonction RELAPATH\n"
 #
 puts "[relapath [pwd]/a/b ]"
 puts "[relapath [abspath [pwd]/../.. ]/a/b]"
 puts "[relapath [pwd]]"
 puts "[relapath /a/b/c/d]"
 puts "[relapath "/o/c/g/../z"]"
 #
    }
    if {$tcl_platform(platform) == "windows" } {
 puts " ======= fonction ABSPATH\n"
 #
 puts "[abspath C:/udd/lpmn/ocz]"
 puts "[abspath "C:/o/c/g/../z"]"
 puts "[abspath C:/a/b/f/..]"
 puts "[abspath ../d/k/r]"
 #
 puts " ======= fonction RELAPATH\n"
 #
 puts "[relapath [pwd]/a/b ]"
 puts "[relapath [abspath [pwd]/../.. ]/a/b]"
 puts "[relapath [pwd]]"
 puts "[relapath C:/a/b/c/d]"
 puts "[relapath "C:/o/c/g/../z"]"
 #
    }
 #

                  Resultat

 #
 # SYSTEME UNIX
 # =======================================================

  ======= fonction ABSPATH

 /udd/lpmn/ocz
 /o/c/z
 /a/b
 /udd/udd2/ocz/tcltk/wikit/d/k/r
  ======= fonction RELAPATH

 a/b
 ../../a/b
 .
 /a/b/c/d

  erreur relapath : /o/c/g/../z
  le repertoire doit etre designe en absolu

 #
 # SYSTEME WINDOWS
 # =======================================================

  ======= fonction ABSPATH

 C:/udd/lpmn/ocz
 C:/o/c/z
 C:/a/b
 C:/udd/udd2/ocz/tcltk/wikit/d/k/r
  ======= fonction RELAPATH

 a/b
 ../../a/b
 .
 C:/a/b/c/d

  erreur relapath : C:/o/c/g/../z
  le repertoire doit etre designe en absolu

 # =======================================================

Il pourrait etre envisage de rajouter 2 attributs a la fonction TCL file : absolute et relative ,completant ainsi la fonction file pathtype namefich de TCL

on aurait file absolute namefich et file relative namefich qui donneraient pour l'un le chemin absolu comprime et pour l'autre le chemin relatif par rapport a la position de travail.

AM (16 juillet 2004) En effet il existe deja un commande qui fait une telle chose: [file normalize]. Sa fonction est un peu compliquee, a cause de l'existance de "links" sous certains OSes, mais il rend un nom sans segments relatifs.

Par exemple:

   pwd
   ==> /u/markus/tmp
   set dir "../../usr/lib"
   file normalize $dir
   ==> /users/homes/usr/lib

(sous un des systemes UNIX que je peuz utiliser)


OCZ(26 juillet 2004) : J'ai ecrit une utilisation de ceci dans un exemple de lanceur de procs