Question: existe-t-il une simple commande sh/bash/zsh/fish/... permettant d’imprimer le chemin absolu du fichier que je l’alimente?
Cas d'utilisation: je suis dans le répertoire /a/b
et j'aimerais imprimer le chemin complet du fichier c
sur la ligne de commande afin de pouvoir le coller facilement dans un autre programme: /a/b/c
. Simple, mais un petit programme pour faire cela pourrait probablement me faire gagner environ 5 secondes quand il s’agit de gérer de longs chemins, ce qui au final s’additionne. Donc, cela me surprend que je ne trouve pas d’utilitaire standard pour le faire - n’y at-il vraiment aucun?
Voici un exemple d'implémentation, abspath.py:
#!/usr/bin/python
# Author: Diggory Hardy <[email protected]>
# Licence: public domain
# Purpose: print the absolute path of all input paths
import sys
import os.path
if len(sys.argv)>1:
for i in range(1,len(sys.argv)):
print os.path.abspath( sys.argv[i] )
sys.exit(0)
else:
print >> sys.stderr, "Usage: ",sys.argv[0]," PATH."
sys.exit(1)
Essayez realpath
.
$ realpath example.txt
/home/username/example.txt
Essayez readlink
qui résoudra les liens symboliques:
readlink -e /foo/bar/baz
#! /bin/sh
echo "$(cd "$(dirname "$1")"; pwd -P)/$(basename "$1")"
Oubliez readlink
et realpath
qui peuvent être installés ou non sur votre système.
Développer sur réponse de dogbane ci-dessus, ici, il est exprimé en fonction:
#!/bin/bash
get_abs_filename() {
# $1 : relative filename
echo "$(cd "$(dirname "$1")" && pwd)/$(basename "$1")"
}
vous pouvez ensuite l'utiliser comme ceci:
myabsfile=$(get_abs_filename "../../foo/bar/file.txt")
La solution exploite le fait que la commande intégrée Bash pwd
imprimera le chemin absolu du répertoire en cours lorsqu'elle est appelée sans arguments.
Il est portable et ne nécessite ni readlink
ni realpath
qui n’existent souvent pas lors d’une installation par défaut d’une distribution Linux/Unix donnée.
Comme indiqué ci-dessus, la fonction échouera et imprimera sur stderr si le chemin du répertoire indiqué n'existe pas. Cela peut ne pas être ce que vous voulez. Vous pouvez développer la fonction pour gérer cette situation:
#!/bin/bash
get_abs_filename() {
# $1 : relative filename
if [ -d "$(dirname "$1")" ]; then
echo "$(cd "$(dirname "$1")" && pwd)/$(basename "$1")"
fi
}
Maintenant, il retournera une chaîne vide si les répertoires parents n'existent pas.
Eh bien, dans ce cas, cela donne un chemin absolu, mais pas minimal. Cela ressemblera à:
/Users/bob/Documents/..
Si vous voulez résoudre le '..' vous devrez faire le script comme suit:
get_abs_filename() {
# $1 : relative filename
filename=$1
parentdir=$(dirname "${filename}")
if [ -d "${filename}" ]; then
echo "$(cd "${filename}" && pwd)"
Elif [ -d "${parentdir}" ]; then
echo "$(cd "${parentdir}" && pwd)/$(basename "${filename}")"
fi
}
$ readlink -m FILE
/path/to/FILE
C'est mieux que readlink -e FILE
ou realpath
, car cela fonctionne même si le fichier n'existe pas.
Ce chemin relatif au convertisseur de chemin absolu Fonction Shell
cd
et pwd
)..
et .
Code:
function abspath() {
# generate absolute path from relative path
# $1 : relative filename
# return : absolute path
if [ -d "$1" ]; then
# dir
(cd "$1"; pwd)
Elif [ -f "$1" ]; then
# file
if [[ $1 = /* ]]; then
echo "$1"
Elif [[ $1 == */* ]]; then
echo "$(cd "${1%/*}"; pwd)/${1##*/}"
else
echo "$(pwd)/$1"
fi
fi
}
Échantillon:
# assume inside /parent/cur
abspath file.txt => /parent/cur/file.txt
abspath . => /parent/cur
abspath .. => /parent
abspath ../dir/file.txt => /parent/dir/file.txt
abspath ../dir/../dir => /parent/dir # anything cd can handle
abspath doesnotexist => # empty result if file/dir does not exist
abspath /file.txt => /file.txt # handle absolute path input
Remarque: Ceci est basé sur les réponses de nolan60 et bsingh , mais corrige la casse du fichier.
Je comprends aussi que la question initiale concernait un utilitaire de ligne de commande existant. Mais puisque cela semble être LA question sur stackoverflow pour cela, y compris les scripts Shell qui veulent avoir des dépendances minimales, je mets cette solution de script ici, afin que je puisse la trouver plus tard:)
La commande find
peut aider
find $PWD -name ex*
find $PWD -name example.log
Répertorie tous les fichiers situés dans ou sous le répertoire actuel avec des noms correspondant au modèle. Vous pouvez le simplifier si vous n’obtenez que quelques résultats (par exemple, un répertoire au bas de l’arbre contenant quelques fichiers),
find $PWD
J'utilise ceci sur Solaris 10, qui ne contient pas les autres utilitaires mentionnés.
Si vous n'avez pas d'utilitaires readlink ou realpath, vous pouvez utiliser la fonction suivante qui fonctionne dans bash et zsh (pas sûr du reste).
abspath () { case "$1" in /*)printf "%s\n" "$1";; *)printf "%s\n" "$PWD/$1";; esac; }
Cela fonctionne également pour les fichiers inexistants (comme la fonction python _ os.path.abspath
).
Malheureusement, abspath ./../somefile
ne supprime pas les points.
Voici une fonction uniquement zsh que j'aime pour sa compacité. Il utilise le modificateur d’expansion ‘A’ - voir zshexpn (1).
realpath() { for f in "$@"; do echo ${f}(:A); done }
Il n’existe généralement pas de le absolute path
dans un fichier (cette déclaration signifie qu’il peut y en avoir plus d’un en général, d’où le l'utilisation de l'article défini le n'est pas appropriée). Un absolute path
est un chemin commençant par la racine "/" et désignant un fichier sans ambiguïté indépendamment du répertoire de travail (voir par exemple wikipedia ).
Un relative path
est un chemin à interpréter à partir d'un autre répertoire. Il peut s'agir du répertoire de travail s'il s'agit d'un relative path
manipulé par une application (mais pas nécessairement). Lorsqu'il se trouve dans un lien symbolique dans un répertoire, il est généralement destiné à être relatif à ce répertoire (bien que l'utilisateur puisse avoir d'autres utilisations à l'esprit).
Par conséquent, un chemin absolu est simplement un chemin relatif au répertoire racine.
Un chemin (absolu ou relatif) peut contenir ou non des liens symboliques. Si ce n'est pas le cas, il est également quelque peu imperméable aux modifications de la structure de liaison, mais cela n'est pas nécessairement requis ni même souhaitable. Certaines personnes appellent canonical path
(ou canonical file name
ou resolved path
) un absolute path
dans lequel tous les liens symboliques ont été résolus, c'est-à-dire qu'ils ont été remplacés par un chemin d'accès, quel que soit leur lien. Les commandes realpath
et readlink
recherchent toutes les deux un chemin canonique, mais seul realpath
a une option permettant d’obtenir un chemin absolu sans se soucier de résoudre les liens symboliques (ainsi que plusieurs autres options permettant d'obtenir divers type de chemin, absolu ou relatif à un répertoire).
Cela appelle plusieurs remarques:
realpath
et readlink
ont des options pour rendre compte de cela.canonical
. Par conséquent, le concept dépend du temps (ou de l'environnement).canonical path
dans un fichier, pour deux raisons: ro
) sur plusieurs points de montage.Par conséquent, même avec la définition beaucoup plus restrictive de canonical path
, il peut y avoir plusieurs chemins canoniques vers un fichier. Cela signifie également que le qualificatif canonical
est quelque peu insuffisant puisqu'il implique généralement une notion d'unicité.
Cela développe une brève discussion du sujet dans une réponse à une autre question similaire à Bash: récupérer le chemin absolu donné relatif
Ma conclusion est que realpath
est mieux conçu et beaucoup plus souple que readlink
. La seule utilisation de readlink
qui n'est pas couverte par realpath
est l'appel sans option qui renvoie la valeur d'un lien symbolique.
La dogbane
réponse avec la description de ce qui va arriver:
#! /bin/sh
echo "$(cd "$(dirname "$1")"; pwd)/$(basename "$1")"
Explication:
"$1"
dirname "$1"
cd "$(dirname "$1")
dans ce répertoire relatif et obtenons son chemin absolu en exécutant la commande pwd
Shell$(basename "$1")
echo
ilCe n'est pas une réponse à la question, mais pour ceux qui font du script:
echo `cd "$1" 2>/dev/null&&pwd||(cd "$(dirname "$1")";pwd|sed "s|/*\$|/${1##*/}|")`
il gère/.. ./ etc correctement. Je semble aussi travailler sur OSX
Pour les répertoires dirname
est déclenché pour ../
et renvoie ./
.
fonction de nolan60 peut être modifié pour résoudre ce problème:
get_abs_filename() {
# $1 : relative filename
if [ -d "${1%/*}" ]; then
echo "$(cd ${1%/*}; pwd)/${1##*/}"
fi
}
J'ai placé le script suivant sur mon système et je l'appelle comme un alias bash lorsque je veux saisir rapidement le chemin complet d'un fichier dans le répertoire en cours:
#!/bin/bash
/usr/bin/find "$PWD" -maxdepth 1 -mindepth 1 -name "$1"
Je ne sais pas pourquoi, mais sous OS X, lorsqu'il est appelé par un script, "$ PWD" se développe sur le chemin absolu. Lorsque la commande find est appelée sur la ligne de commande, ce n'est pas le cas. Mais ça fait ce que je veux ... profiter.
#! /bin/bash
file="$@"
realpath "$file" 2>/dev/null || eval realpath $(echo $file | sed 's/ /\\ /g')
Ceci compense les inconvénients de realpath
, enregistrez-le dans un script shell fullpath
. Vous pouvez maintenant appeler:
$ cd && touch a\ a && rm A 2>/dev/null
$ fullpath "a a"
/home/user/a a
$ fullpath ~/a\ a
/home/user/a a
$ fullpath A
A: No such file or directory.
Une alternative pour obtenir le chemin absolu dans Ruby:
realpath() {Ruby -e "require 'Pathname'; puts Pathname.new('$1').realpath.to_s";}
Fonctionne sans argument (dossier actuel) et les chemins de fichiers ou de dossiers relatifs et absolus en tant qu'agument.