Comment obtenir le chemin complet d'un fichier en bash?

22

Je voudrais un moyen facile d'obtenir le chemin d'accès complet à un fichier. Je tape actuellement ceci:

echo `pwd`/file.ext

En essayant de le raccourcir, j'ai fait un alias bash:

alias fp='echo `pwd`/'

Mais maintenant, si je tape fp file.ext, il y a un espace qui apparaît entre le /et le file.ext.

Une telle commande existe-t-elle déjà et je la manque? Sinon, comment pourrais-je créer un tel alias ou une telle fonction dans bash?

Jens Erat
la source

Réponses:

30

Sur les systèmes Linux, vous devriez avoir readlinkdu projet GNU coreutils installé et pouvez le faire:

readlink -f file.ext

Les systèmes Debian / ubuntu peuvent avoir l' utilitaire realpath installé qui "fournit principalement les mêmes fonctionnalités que /bin/readlink -fdans le paquet coreutils."

Doug Harris
la source
readlink -f(ou realpath, qui est un ancien utilitaire conservé à des fins de compatibilité) étendra également tous les liens symboliques, ce qui n'est pas nécessairement souhaitable.
Gilles 'SO- arrête d'être méchant'
8
fyi: ne fonctionne pas sur macosx.
Akira
Sur mon mac, j'ai installé coreutils en utilisant homebrew et cela inclut realpath.
Doug Harris
7

Au lieu de la pwdcommande, utilisez la PWDvariable (c'est aussi dans POSIX):

fp () {
  case "$1" in
    /*) printf '%s\n' "$1";;
    *) printf '%s\n' "$PWD/$1";;
  esac
}

Si vous devez prendre en charge Windows, la reconnaissance des chemins absolus sera plus compliquée car chaque port d'outils Unix a ses propres règles de traduction des chemins de fichiers. Avec Cygwin, utilisez l' cygpathutilitaire.

Gilles 'SO- arrête d'être méchant'
la source
C'est peut-être votre choix, mais cette fonction ne sortira pas la nouvelle ligne.
cYrus
cette approche a l'avantage d'utiliser uniquement des commandes intégrées au shell, ce qui est plus rapide que d'appeler des binaires externes. vous devriez rendre ce fait un peu plus clair.
akira
4

pour répondre à votre question avec ce que vous utilisez actuellement:

l'alias se développe à la position où vous tapez en ce moment. vous avez tapé:

% fp<SPACE>file.ext

cela devient

% echo `pwd`<SPACE>file.exe

vous pouvez utiliser une fonction pour éviter cela:

function fp() {
    echo `pwd`/"$1"
}

vous pouvez l'utiliser comme d'habitude:

% fp file.ext
akira
la source
Vous avez besoin de guillemets doubles autour des substitutions de variables et de commandes:echo "`pwd`/$1"
Gilles 'SO- arrêtez d'être méchant'
@Gilles: dans quelles circonstances?
akira
2
@akira: utilisez toujours des guillemets doubles, sauf si vous souhaitez que le résultat de l'expansion soit traité comme un modèle de globalisation et que les résultats de la globalisation soient divisés en mots. Ici, vous créez un nom de fichier unique, donc les guillemets doubles sont nécessaires (essayez votre fonction avec un fichier appelé *dans un répertoire contenant d'autres fichiers).
Gilles 'SO- arrête d'être méchant'
le ' ' est englobé par le shell (zsh dans mon cas) et développé avant d'appuyer sur la fonction. fp *donne /tmp/4cc3ea0c1b34bpuisque c'est le premier paramètre pour la fonction. les autres paramètres seraient les autres fichiers du répertoire. dès que j'ai un fichier appelé ' ', la fonction fonctionne toujours comme prévu, en l'appelant avec "*" ou * ou *
akira
bash est le "mauvais" ici comme il semble, bash donne ce à quoi vous faites référence.
akira
3

Vous pouvez utiliser:

realpath file.ext
cYrus
la source
Je n'en ai pas. D'où cela vient-il?
frabjous
@frabjous: il est spécifique à Debian et à ses dérivés, et ne sera installé que si vous l'avez demandé ou si un paquet en dépend.
Gilles 'SO- arrête d'être méchant'
J'utilise Arch. Ce n'est pas basé sur Debian, mais il y a quand même un paquet pour cela dans l'AUR. Je ne suis pas sûr que cela vaille la peine d'être installé si j'ai déjà un lien de lecture.
frabjous
Eh bien, c'est une option; ou vous pouvez envisager une fonction, voir la réponse de Gilles . Quoi qu'il en soit, cela dépend de l'utilisation réelle que vous souhaitez en faire (je suis curieux).
cYrus
@frabjous: Vous n'avez pas spécifié sur quel système vous êtes, mais s'il utilise un gestionnaire de paquets basé sur Aptitude (Debian, Ubuntu, Mint, etc.), vous pouvez taper apt-cache search realpathpour révéler que les paquets coreutils et plain ol ' realpath les deux le contiennent. Vous pouvez ensuite taper sudo apt-get install realpath(ou coreutils) pour l'installer.
Michael Scheper
1

Depuis /programming//a/3915420/5795941

C'est la seule façon qui m'est acceptable. N'étend pas les liens comme realpath et readlink et est la façon classique de le faire que j'ai vue partout.

#! /bin/sh
echo "$(cd "$(dirname "$1")"; pwd -P)/$(basename "$1")"
Philippe Carphin
la source