Je recherche une commande simple qui peut être utilisée dans Bash pour trouver le chemin absolu et canonisé d'un fichier sur un OS X (similaire à “ readlink -f'` sous Linux).
L'exemple de session bash suivant décrit un utilitaire [fictif] appelé “ abspath'` qui présente le comportement souhaité:
$ pwd /Users/guyfleegman $ ls -lR drwxr-xr-x 4 guyfleegman crew 136 Oct 30 02:09 foo ./foo: -rw-r--r-- 1 guyfleegman crew 0 Oct 30 02:07 bar.txt lrwxr-xr-x 1 guyfleegman crew 7 Oct 30 02:09 baz.txt -> bar.txt $ abspath . /Users/guyfleegman $ abspath foo /Users/guyfleegman/foo $ abspath ./foo/bar.txt /Users/guyfleegman/foo/bar.txt $ abspath foo/baz.txt /Users/guyfleegman/foo/baz.txt
Comme avec la dernière invocation de “ abspath'` dans l'exemple ci-dessus, je préférerais qu'il ne résolut pas automatiquement les liens symboliques, mais je ne vais pas être trop pointilleux ici.
function abspath() { pushd . > /dev/null; if [ -d "$1" ]; then cd "$1"; dirs -l +0; else cd "`dirname \"$1\"`"; cur_dir=`dirs -l +0`; if [ "$cur_dir" == "/" ]; then echo "$cur_dir`basename \"$1\"`"; else echo "$cur_dir/`basename \"$1\"`"; fi; fi; popd > /dev/null; }
Exemples:
abspath / => / abspath /.DS_Store => /.DS_Store abspath ~ => /Users/mschrag cd /tmp; abspath . => /tmp cd /; abspath .DS_Store => /.DS_Store
Je ne pense pas qu'il y ait une commande buildin qui fait cela. Jesse Wilson a écrit un script bash pour ceci:
#!/bin/bash cd -P -- "$(dirname -- "$1")" && printf '%s\n' "$(pwd -P)/$(basename -- "$1")"
Cependant, cela ne fonctionne pas bien pour les chemins directement en dessous /
, comme /etc
(impression //etc
), ainsi que .
Et ..
(impression /cwd/.
Dans les deux cas). J'ai essayé de le modifier, mais mon bash-fu non suffisant m'a échoué.
Voici ma suggestion:
#!/usr/bin/env python import os.path import sys for arg in sys.argv[1:]: print os.path.abspath(arg)
Enregistrez sous /usr/bin/abspath
ou quelque chose comme ça et rendez-le exécutable. Exemple de sortie:
Servus08:~ danielbeck$ abspath . /Users/danielbeck Servus08:~ danielbeck$ abspath /tmp /tmp Servus08:~ danielbeck$ abspath Documents /Users/danielbeck/Documents Servus08:~ danielbeck$ abspath . /tmp Documents /Users/danielbeck /tmp /Users/danielbeck/Documents
Si vous voulez une résolution de lien symbolique, modifiez la ligne d' print
comme ceci:
print os.path.realpath(os.path.abspath(arg))
Pour obtenir ceci:
Servus08:~ danielbeck$ abspath . /tmp Documents /Users/danielbeck /private/tmp /Users/danielbeck/Documents
Une option serait simplement d'installer coreutils et d'utiliser greadlink -f
. Il résout les liens symboliques et fonctionne avec /Foo/
ou ~/foo.txt
s'ils n'existent pas, mais pas avec /Foo/foo.txt
si /Foo/
n'existe pas.
$ brew install coreutils $ greadlink -f /etc /private/etc $ greadlink -f ~/Documents/ /Users/lauri/Documents $ greadlink -f .. /Users $ greadlink -f //etc/..//// /private $ greadlink -f /Foo /Foo $ greadlink -f /Foo/foo.txt $
Cela ne résout pas les liens symboliques, et cela ne fonctionne pas non plus avec /Foo/foo.txt
.
abspath() { if [ -d "$1" ]; then ( cd "$1"; dirs -l +0 ) else ( cd "$(dirname "$1")"; d=$(dirs -l +0); echo "${d%/}/${1##*/}" ) fi } abspath /etc # /etc abspath ~/Foo/foo.txt # doesn't work abspath ~/Foo # works abspath . abspath ./ abspath ../ abspath .. abspath / abspath ~ abspath ~/ abspath ~/Documents abspath /\"\ \' abspath /etc/../etc/ abspath /private//etc/ abspath /private// abspath //private # //private abspath ./aa.txt abspath aa.tar.gz abspath .aa.txt abspath /.DS_Store abspath ~/Documents/Books/
dirs -l
effectue une expansion tilde. dirs +0
imprime uniquement le répertoire supérieur s'il existe d'autres répertoires dans la pile.
Je suppose que vous pourriez le faire avec Python ou Ruby.
$ ruby -e 'puts File.expand_path("~/somepath")'
Ou faire une commande avec
#!/usr/bin/env ruby puts File.expand_path(ARGV[0])
Si vous avez le module File :: Spec installé pour perl, vous pouvez simplement le faire:
perl -MFile::Spec -e 'print File::Spec->rel2abs("../however/complex/../you/want/to.get"), "\n"'
Pour les scripts bash / sh, vous pouvez utiliser cette fonction récursive:
canonical_readlink () { cd `dirname $1`; __filename=`basename $1`; if [ -h "$__filename" ]; then canonical_readlink `readlink $__filename`; else echo "`pwd -P`"; fi } answer=$(canonical_readlink $0)
Installez la bibliothèque suivante pour OSX:
brew install coreutils greadlink -f file.txt