realpathne semble pas disponible sur Mac (OS X 10.11 "El Capitan"). :-(
Laryx Decidua
realpathne semble pas non plus disponible sur CentOS 6
user5359531
6
sur osx, brew install coreutilsapporterarealpath
Kevin Chen
Sur mon Ubuntu 18.04, realpathest déjà présent. Je n'ai pas eu à l'installer séparément.
Acumenus
Étonnamment, realpathest disponible sur Git pour Windows (pour moi, du moins).
Andrew Keeton
104
Si vous avez installé le package coreutils, vous pouvez généralement l'utiliser readlink -f relative_file_namepour récupérer le package absolu (avec tous les liens symboliques résolus)
Le comportement pour cela est un peu différent de ce que l'utilisateur demande, il suivra également et résoudra les liens symboliques récursifs n'importe où dans le chemin. Vous pourriez ne pas vouloir cela dans certains cas.
ffledgling
1
@BradPeabody Cela fonctionne sur un Mac si vous installez coreutils depuis homebrew brew install coreutils. Cependant l'exécutable est précédé de ag:greadlink -f relative_file_name
Miguel Isla
2
Notez que la page de manuel de readlink (1) a comme première phrase de sa description: "Notez que realpath (1) est la commande préférée à utiliser pour la fonctionnalité de canonisation."
josch
1
vous pouvez utiliser -e au lieu de -f pour vérifier si le fichier / répertoire existe ou non
readlink est la solution simple pour linux, mais cette solution fonctionne aussi sur OSX, donc +1
thetoolman
1
Ce script n'est pas équivalent à quoi realpathou readlink -ffaire. Par exemple, cela ne fonctionne pas sur les chemins où le dernier composant est un lien symbolique.
josch
2
@josch: La question ne concerne pas la résolution des liens symboliques. Mais si vous voulez faire cela, vous pouvez fournir une -Poption pour pwdcommander:echo "$(cd "$(dirname "$1")"; pwd -P)/$(basename "$1")"
Eugen Konkov
4
J'aime la réponse, mais cela ne fonctionne que si l'utilisateur est autorisé à CD dans le répertoire. Cela n'est peut-être pas toujours possible.
Matthias B
34
Pour ce que ça vaut, j'ai voté pour la réponse choisie, mais je voulais partager une solution. L'inconvénient est qu'il ne s'agit que de Linux - j'ai passé environ 5 minutes à essayer de trouver l'équivalent OSX avant d'arriver à Stack overflow. Je suis sûr que c'est là-bas cependant.
Sous Linux, vous pouvez utiliser readlink -een tandem avec dirname.
$(dirname $(readlink -e ../../../../etc/passwd))
rendements
/etc/
Et puis vous utilisez dirnamela sœur de, basenamepour simplement obtenir le nom du fichier
Vous êtes en sécurité si vous ciblez un répertoire, basenamene retournera rien et vous vous retrouverez simplement avec des doubles barres obliques dans la sortie finale.
Entrée excellente avec dirname, readlinket basename. Cela m'a aidé à trouver le chemin absolu d'un lien symbolique - pas sa cible.
kevinarpe
Ne fonctionne pas lorsque vous souhaitez retourner le chemin vers des liens symboliques (ce que je dois juste faire ...).
Tomáš Zato - Réintégrer Monica le
Comment pourriez-vous trouver le chemin absolu vers un chemin qui n'existe pas?
synthesizerpatel
@synthesizerpatel Assez facilement, j'aurais pensé; si je suis dedans /home/GKFXet que je tape touch newfile, alors avant d'appuyer sur Entrée, vous pourriez comprendre que je veux dire "create / home / GKFX / newfile", qui est un chemin absolu vers un fichier qui n'existe pas encore.
GKFX
25
Je pense que c'est le plus portable:
abspath(){
cd "$(dirname "$1")"
printf "%s/%s\n""$(pwd)""$(basename "$1")"
cd "$OLDPWD"}
Il n'est pas nécessaire de recadrer le cd. Voir stackoverflow.com/a/21188136/1504556 . Votre est la meilleure réponse sur cette page, à mon humble avis. Pour les personnes intéressées, le lien explique pourquoi cette solution fonctionne.
peterh le
Ce n'est pas très portable, dirnamec'est un utilitaire de base GNU, pas commun à tous les Unixen je crois.
Oh mon Dieu, merci. J'essaie de réparer la version qui utilise ${1##*/}depuis un jour maintenant, et maintenant que j'ai remplacé cette poubelle par basename "$1"elle semble enfin gérer correctement les chemins qui se terminent par /.
l3l_aze
NB, cela ne fait pas la bonne chose avec un chemin se terminant par../..
Alex Coventry
16
realpath est probablement le meilleur
Mais ...
La question initiale était très confuse au départ, avec un exemple mal lié à la question comme indiqué.
La réponse choisie répond en fait à l'exemple donné, et pas du tout à la question du titre. La première commande est cette réponse (est-ce vraiment? Je doute), et pourrait faire aussi bien sans le '/'. Et je ne vois pas ce que fait la deuxième commande.
Plusieurs problèmes sont mitigés:
changer un chemin relatif en chemin absolu, quoi qu'il dénote, peut-être rien. ( En règle générale, si vous exécutez une commande telle que touch foo/bar, le chemin d'accès foo/bardoit exister pour vous, et éventuellement être utilisé dans le calcul, avant que le fichier ne soit réellement créé. )
il peut y avoir plusieurs chemins absolus qui désignent le même fichier (ou fichier potentiel), notamment à cause de liens symboliques (symlinks) sur le chemin, mais éventuellement pour d'autres raisons (un périphérique peut être monté deux fois en lecture seule). On peut ou non vouloir résoudre explicitement ces liens symboliques.
arriver à la fin d'une chaîne de liens symboliques vers un fichier ou un nom sans lien symbolique. Cela peut ou non donner un nom de chemin absolu, selon la façon dont cela est fait. Et on peut, ou peut ne pas vouloir le résoudre en un chemin absolu.
La commande readlink foosans option donne une réponse uniquement si son argument fooest un lien symbolique, et cette réponse est la valeur de ce lien symbolique. Aucun autre lien n'est suivi. La réponse peut être un chemin relatif: quelle que soit la valeur de l'argument du lien symbolique.
Cependant, readlinka des options (-f -e ou -m) qui fonctionneront pour tous les fichiers, et donneront un chemin absolu (celui sans lien symbolique) au fichier réellement indiqué par l'argument.
Cela fonctionne bien pour tout ce qui n'est pas un lien symbolique, bien que l'on puisse souhaiter utiliser un chemin absolu sans résoudre les liens symboliques intermédiaires sur le chemin. Ceci est fait par la commanderealpath -s foo
Dans le cas d'un argument de lien symbolique, readlinkavec ses options résoudra à nouveau tous les liens symboliques sur le chemin absolu de l'argument, mais cela inclura également tous les liens symboliques qui peuvent être rencontrés en suivant la valeur de l'argument. Vous ne voudrez peut-être pas cela si vous souhaitez un chemin absolu vers le lien symbolique de l'argument lui-même, plutôt que vers celui auquel il peut être lié. Encore une fois, si fooest un lien symbolique, realpath -s fooobtiendra un chemin absolu sans résoudre les liens symboliques, y compris celui donné en argument.
Sans l' -soption, realpathfait à peu près la même chose que
readlink, sauf pour simplement lire la valeur d'un lien, ainsi que plusieurs autres choses. Il n'est tout simplement pas clair pour moi pourquoi readlinka ses options, créant apparemment une redondance indésirable avec
realpath.
Explorer le Web ne dit pas grand chose de plus, sauf qu'il peut y avoir des variations entre les systèmes.
Conclusion: realpathc'est la meilleure commande à utiliser, avec le plus de flexibilité, du moins pour l'utilisation demandée ici.
Ma solution préférée était celle de @EugenKonkov car elle n'impliquait pas la présence d'autres utilitaires (le package coreutils).
Mais il a échoué pour les chemins relatifs "." et "..", voici donc une version légèrement améliorée gérant ces cas particuliers.
cdCependant, cela échoue toujours si l'utilisateur n'a pas l'autorisation d' accéder au répertoire parent du chemin relatif.
#! /bin/sh# Takes a path argument and returns it as an absolute path. # No-op if the path is already absolute.function to-abs-path {local target="$1"if["$target"=="."];then
echo "$(pwd)"elif["$target"==".."];then
echo "$(dirname "$(pwd)")"else
echo "$(cd "$(dirname "$1")"; pwd)/$(basename "$1")"fi}
Si vous utilisez bash sur Mac OS X qui n'a pas de realpath et que son readlink peut imprimer le chemin absolu, vous pouvez avoir le choix de coder votre propre version pour l'imprimer. Voici ma mise en œuvre:
(pure bash)
abspath(){local thePath
if[[!"$1"=~^/]];then
thePath="$PWD/$1"else
thePath="$1"fi
echo "$thePath"|(
IFS=/
read -a parr
declare -a outp
for i in"${parr[@]}";docase"$i"in''|.)continue;;..)
len=${#outp[@]}if((len==0));thencontinueelse
unset outp[$((len-1))]fi;;*)
len=${#outp[@]}
outp[$len]="$i";;esacdone
echo /"${outp[*]}")}
(utilisez gawk)
abspath_gawk(){if[[-n "$1"]];then
echo $1|gawk '{
if(substr($0,1,1) != "/"){
path = ENVIRON["PWD"]"/"$0
} else path = $0
split(path, a, "/")
n = asorti(a, b,"@ind_num_asc")
for(i in a){
if(a[i]=="" || a[i]=="."){
delete a[i]
}
}
n = asorti(a, b, "@ind_num_asc")
m = 0
while(m!=n){
m = n
for(i=1;i<=n;i++){
if(a[b[i]]==".."){
if(b[i-1] in a){
delete a[b[i-1]]
delete a[b[i]]
n = asorti(a, b, "@ind_num_asc")
break
} else exit 1
}
}
}
n = asorti(a, b, "@ind_num_asc")
if(n==0){
printf "/"
} else {
for(i=1;i<=n;i++){
printf "/"a[b[i]]
}
}
}'fi}
Merci pour cet extrait de code, qui pourrait fournir une aide limitée à court terme. Une explication appropriée améliorerait considérablement sa valeur à long terme en montrant pourquoi c'est une bonne solution au problème, et la rendrait plus utile aux futurs lecteurs avec d'autres questions similaires. Veuillez modifier votre réponse pour ajouter des explications, y compris les hypothèses que vous avez formulées.
Toby Speight
1
Une amélioration de la version plutôt sympa de @ ernest-a:
Cela traite correctement le cas où se trouve le dernier élément du chemin .., auquel cas la "$(pwd)/$(basename "$1")"réponse de in @ ernest-a apparaîtra comme accurate_sub_path/spurious_subdirectory/...
Sur bash-4.3-p46, cela ne fonctionne pas: le shell imprime une ligne vide lorsque je coursdir=`cd ".."` && echo $dir
Michael
0
Il s'agit d'une solution chaînée de toutes les autres, par exemple, en cas d' realpathéchec, soit parce qu'elle n'est pas installée, soit parce qu'elle se termine avec un code d'erreur, la solution suivante est tentée jusqu'à ce qu'elle obtienne le bon chemin.
Je n'ai pas pu trouver une solution parfaitement portable entre Mac OS Catalina, Ubuntu 16 et Centos 7, j'ai donc décidé de le faire avec python inline et cela a bien fonctionné pour mes scripts bash.
Réponses:
utilisation:
pour obtenir tous les fichiers ou
pour afficher le chemin complet (si le chemin relatif est important)
la source
$(pwd)
à la place de$PWD
? (oui, je sais quepwd
c'est un builtin)Essayez
realpath
.Pour éviter de développer les liens symboliques, utilisez
realpath -s
.La réponse vient de " la commande bash / fish pour imprimer le chemin absolu vers un fichier ".
la source
realpath
ne semble pas disponible sur Mac (OS X 10.11 "El Capitan"). :-(realpath
ne semble pas non plus disponible sur CentOS 6brew install coreutils
apporterarealpath
realpath
est déjà présent. Je n'ai pas eu à l'installer séparément.realpath
est disponible sur Git pour Windows (pour moi, du moins).Si vous avez installé le package coreutils, vous pouvez généralement l'utiliser
readlink -f relative_file_name
pour récupérer le package absolu (avec tous les liens symboliques résolus)la source
brew install coreutils
. Cependant l'exécutable est précédé de ag:greadlink -f relative_file_name
UPD Quelques explications
"$1"
dirname "$1"
cd "$(dirname "$1")
dans ce répertoire relatif et obtenons le chemin absolu pour celui-ci en exécutant lapwd
commande shell$(basename "$1")
echo
nela source
realpath
oureadlink -f
faire. Par exemple, cela ne fonctionne pas sur les chemins où le dernier composant est un lien symbolique.-P
option pourpwd
commander:echo "$(cd "$(dirname "$1")"; pwd -P)/$(basename "$1")"
Pour ce que ça vaut, j'ai voté pour la réponse choisie, mais je voulais partager une solution. L'inconvénient est qu'il ne s'agit que de Linux - j'ai passé environ 5 minutes à essayer de trouver l'équivalent OSX avant d'arriver à Stack overflow. Je suis sûr que c'est là-bas cependant.
Sous Linux, vous pouvez utiliser
readlink -e
en tandem avecdirname
.rendements
Et puis vous utilisez
dirname
la sœur de,basename
pour simplement obtenir le nom du fichierrendements
Mets le tout ensemble..
rendements
Vous êtes en sécurité si vous ciblez un répertoire,
basename
ne retournera rien et vous vous retrouverez simplement avec des doubles barres obliques dans la sortie finale.la source
dirname
,readlink
etbasename
. Cela m'a aidé à trouver le chemin absolu d'un lien symbolique - pas sa cible./home/GKFX
et que je tapetouch newfile
, alors avant d'appuyer sur Entrée, vous pourriez comprendre que je veux dire "create / home / GKFX / newfile", qui est un chemin absolu vers un fichier qui n'existe pas encore.Je pense que c'est le plus portable:
Cela échouera si le chemin n'existe pas.
la source
dirname
c'est un utilitaire de base GNU, pas commun à tous les Unixen je crois.dirname
est un utilitaire standard POSIX, voir ici: pubs.opengroup.org/onlinepubs/9699919799/utilities/dirname.html${1##*/}
depuis un jour maintenant, et maintenant que j'ai remplacé cette poubelle parbasename "$1"
elle semble enfin gérer correctement les chemins qui se terminent par /.../..
realpath
est probablement le meilleurMais ...
La question initiale était très confuse au départ, avec un exemple mal lié à la question comme indiqué.
La réponse choisie répond en fait à l'exemple donné, et pas du tout à la question du titre. La première commande est cette réponse (est-ce vraiment? Je doute), et pourrait faire aussi bien sans le '/'. Et je ne vois pas ce que fait la deuxième commande.
Plusieurs problèmes sont mitigés:
changer un chemin relatif en chemin absolu, quoi qu'il dénote, peut-être rien. ( En règle générale, si vous exécutez une commande telle que
touch foo/bar
, le chemin d'accèsfoo/bar
doit exister pour vous, et éventuellement être utilisé dans le calcul, avant que le fichier ne soit réellement créé. )il peut y avoir plusieurs chemins absolus qui désignent le même fichier (ou fichier potentiel), notamment à cause de liens symboliques (symlinks) sur le chemin, mais éventuellement pour d'autres raisons (un périphérique peut être monté deux fois en lecture seule). On peut ou non vouloir résoudre explicitement ces liens symboliques.
arriver à la fin d'une chaîne de liens symboliques vers un fichier ou un nom sans lien symbolique. Cela peut ou non donner un nom de chemin absolu, selon la façon dont cela est fait. Et on peut, ou peut ne pas vouloir le résoudre en un chemin absolu.
La commande
readlink foo
sans option donne une réponse uniquement si son argumentfoo
est un lien symbolique, et cette réponse est la valeur de ce lien symbolique. Aucun autre lien n'est suivi. La réponse peut être un chemin relatif: quelle que soit la valeur de l'argument du lien symbolique.Cependant,
readlink
a des options (-f -e ou -m) qui fonctionneront pour tous les fichiers, et donneront un chemin absolu (celui sans lien symbolique) au fichier réellement indiqué par l'argument.Cela fonctionne bien pour tout ce qui n'est pas un lien symbolique, bien que l'on puisse souhaiter utiliser un chemin absolu sans résoudre les liens symboliques intermédiaires sur le chemin. Ceci est fait par la commande
realpath -s foo
Dans le cas d'un argument de lien symbolique,
readlink
avec ses options résoudra à nouveau tous les liens symboliques sur le chemin absolu de l'argument, mais cela inclura également tous les liens symboliques qui peuvent être rencontrés en suivant la valeur de l'argument. Vous ne voudrez peut-être pas cela si vous souhaitez un chemin absolu vers le lien symbolique de l'argument lui-même, plutôt que vers celui auquel il peut être lié. Encore une fois, sifoo
est un lien symbolique,realpath -s foo
obtiendra un chemin absolu sans résoudre les liens symboliques, y compris celui donné en argument.Sans l'
-s
option,realpath
fait à peu près la même chose quereadlink
, sauf pour simplement lire la valeur d'un lien, ainsi que plusieurs autres choses. Il n'est tout simplement pas clair pour moi pourquoireadlink
a ses options, créant apparemment une redondance indésirable avecrealpath
.Explorer le Web ne dit pas grand chose de plus, sauf qu'il peut y avoir des variations entre les systèmes.
Conclusion:
realpath
c'est la meilleure commande à utiliser, avec le plus de flexibilité, du moins pour l'utilisation demandée ici.la source
Ma solution préférée était celle de @EugenKonkov car elle n'impliquait pas la présence d'autres utilitaires (le package coreutils).
Mais il a échoué pour les chemins relatifs "." et "..", voici donc une version légèrement améliorée gérant ces cas particuliers.
cd
Cependant, cela échoue toujours si l'utilisateur n'a pas l'autorisation d' accéder au répertoire parent du chemin relatif.la source
La réponse d'Eugen n'a pas vraiment fonctionné pour moi, mais cela a fonctionné:
Remarque: votre répertoire de travail actuel n'est pas affecté.
la source
La meilleure solution, à mon humble avis, est celle publiée ici: https://stackoverflow.com/a/3373298/9724628 .
Cela nécessite python pour fonctionner, mais il semble couvrir tous ou la plupart des cas marginaux et être une solution très portable.
la source
Dans le cas de
find
, il est probablement plus simple de donner simplement le chemin absolu dans lequel effectuer la recherche, par exemple:la source
Si vous utilisez bash sur Mac OS X qui n'a pas de realpath et que son readlink peut imprimer le chemin absolu, vous pouvez avoir le choix de coder votre propre version pour l'imprimer. Voici ma mise en œuvre:
(pure bash)
(utilisez gawk)
(pure bsd awk)
exemple:
la source
Ce qu'ils ont dit, sauf
find $PWD
ou (en bash)find ~+
est un peu plus pratique.la source
Similaire à la réponse de @ ernest-a mais sans affecter
$OLDPWD
ou définir une nouvelle fonction, vous pouvez déclencher un sous-shell(cd <path>; pwd)
la source
Si le chemin relatif est un chemin de répertoire, essayez le mien, cela devrait être le meilleur:
la source
la source
Une amélioration de la version plutôt sympa de @ ernest-a:
Cela traite correctement le cas où se trouve le dernier élément du chemin
..
, auquel cas la"$(pwd)/$(basename "$1")"
réponse de in @ ernest-a apparaîtra commeaccurate_sub_path/spurious_subdirectory/..
.la source
Si vous souhaitez transformer une variable contenant un chemin relatif en un chemin absolu, cela fonctionne:
"cd" fait écho sans changer le répertoire de travail, car exécuté ici dans un sous-shell.
la source
dir=`cd ".."` && echo $dir
Il s'agit d'une solution chaînée de toutes les autres, par exemple, en cas d'
realpath
échec, soit parce qu'elle n'est pas installée, soit parce qu'elle se termine avec un code d'erreur, la solution suivante est tentée jusqu'à ce qu'elle obtienne le bon chemin.la source
Vous pouvez utiliser la substitution de chaîne bash pour n'importe quel chemin relatif $ line:
La substitution de base avant de chaîne suit la formule
$ {string / # substring / replacement}
qui est bien discutée ici: https://www.tldp.org/LDP/abs/html/string-manipulation.html
Le
\
caractère annule le/
lorsque nous voulons qu'il fasse partie de la chaîne que nous trouvons / remplaçons.la source
Je n'ai pas pu trouver une solution parfaitement portable entre Mac OS Catalina, Ubuntu 16 et Centos 7, j'ai donc décidé de le faire avec python inline et cela a bien fonctionné pour mes scripts bash.
la source