683 votes

Comment obtenir le chemin absolu d'un fichier via le Shell (BASH/ZSH/SH) ?

Question : existe-t-il une commande simple sh/bash/zsh/fish/... pour imprimer le chemin absolu de n'importe quel fichier que je lui envoie ?

Cas d'utilisation : Je suis dans le répertoire /a/b et je voudrais imprimer le chemin complet vers le fichier c sur la ligne de commande afin que je puisse facilement le coller dans un autre programme : /a/b/c . C'est simple, mais un petit programme pour faire cela pourrait probablement me faire gagner 5 secondes environ lorsqu'il s'agit de gérer de longs chemins, ce qui, au final, s'additionne. Je suis donc surpris de ne pas trouver d'utilitaire standard pour faire cela - n'en existe-t-il vraiment pas ?

Voici un exemple d'implémentation, abspath.py :

#!/usr/bin/python
# Author: Diggory Hardy <diggory.hardy@gmail.com>
# 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)

0 votes

Je dirais que la réponse de @DennisWilliamson (en utilisant l'option -m) est supérieure pour (généralement) être plus portable et travailler avec des fichiers qui n'existent pas.

0 votes

Ou la réponse de Flimm ; les deux sont de bonnes solutions. Les réponses de Bannier cependant mon la meilleure question originale.

3 votes

Utilisateurs d'OSX : voir cette réponse

929voto

Benjamin Bannier Points 11953

Utilice realpath

$ realpath example.txt
/home/username/example.txt

185 votes

+1, très beau programme. Mais notez qu'il s'agit d'une commande externe (pas d'une commande intégrée à l'interpréteur de commandes) et qu'elle n'est peut-être pas présente par défaut dans tous les systèmes, c'est-à-dire que vous devrez peut-être l'installer. Dans Debian, il réside dans un paquet séparé portant le même nom.

0 votes

Exactement ce que je cherchais, merci ! La seule question est de savoir pourquoi je ne l'ai pas trouvé moi-même...

0 votes

Il est vrai qu'il n'est pas intégré, mais ce n'est généralement un problème que lorsque l'on utilise des ordinateurs universitaires verrouillés.

373voto

Dennis Williamson Points 105818

Essayez readlink qui résoudra les liens symboliques :

readlink -e /foo/bar/baz

62 votes

Je préférerais utiliser '-f' au lieu de '-e' afin que nous puissions voir le chemin absolu d'un fichier inexistant.

5 votes

Cela me semble le plus simple, tout en étant portable. readlink est un portage des gnu coreutils, il sera donc installé sur presque toutes les distributions linux, à l'exception de celles qui sont intégrées.

19 votes

Il me semble que -m est la meilleure option à utiliser.

321voto

dogbane Points 85749
#! /bin/sh
echo "$(cd "$(dirname "$1")"; pwd -P)/$(basename "$1")"

8 votes

N'oubliez pas de citer tous les éléments. Si vous ne comprenez pas pourquoi, essayez votre programme sur un fichier a b (deux espaces entre a et b, SO mange l'un d'entre eux).

1 votes

Essayez aussi sur "/", cela devient "///".

41 votes

La seule solution POSIX à ce jour qui ne nécessite pas d'écrire et de compiler un exécutable puisque readlink et realpath ne sont pas POSIX.

121voto

nolan6000 Points 1511

Oubliez readlink y realpath qui peut ou non être installé sur votre système.

Élargir le champ d'action Réponse de dogbane ci-dessus, elle est exprimée ici sous forme de fonction :

#!/bin/bash
get_abs_filename() {
  # $1 : relative filename
  echo "$(cd "$(dirname "$1")" && pwd)/$(basename "$1")"
}

vous pouvez alors l'utiliser comme ceci :

myabsfile=$(get_abs_filename "../../foo/bar/file.txt")

Comment et pourquoi cela fonctionne-t-il ?

La solution exploite le fait que la commande intégrée de Bash pwd imprimera le chemin absolu du répertoire courant lorsqu'elle est invoquée sans arguments.

Pourquoi cette solution me plaît-elle ?

Il est portable et ne nécessite ni readlink o realpath qui souvent n'existe pas dans l'installation par défaut d'une distro Linux/Unix donnée.

Et si dir n'existait pas ?

Comme indiqué ci-dessus, la fonction échouera et imprimera sur stderr si le chemin du répertoire donné n'existe pas. Ce n'est peut-être pas 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 l'un des répertoires parents n'existe pas.

Comment gérez-vous la fin du " " ou du " " en entrée ?

Dans ce cas, il donne un chemin absolu, mais pas un chemin minimal. Cela ressemblera à :

/Users/bob/Documents/..

Si vous voulez résoudre le ' ', vous devrez faire le script comme :

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
}

0 votes

Belle fonction, mais apparemment vous n'avez pas compris la question. Je voulais quelque chose pour une utilisation interactive, pas des scripts.

1 votes

@dhardy. Je ne suis pas sûr de comprendre votre commentaire. Qu'y a-t-il dans la solution proposée ici qui exclut l'utilisation dans un environnement interactif ? ... btw, comme toutes les autres réponses alternatives présentées sur cette page.

0 votes

Eh bien, nolan6000, j'ai inclus un script capable (bien qu'inélégant) de faire cela dans la question, qui demandait ensuite s'il y avait un utilitaire Unix standard pour faire la même chose. Je suis surpris par toutes les autres réponses aussi pour être honnête - realpath couvre le cas d'utilisation original et readlink certains cas connexes, donc encore une autre réponse n'aide pas.

81voto

Flimm Points 8870
$ readlink -m FILE
/path/to/FILE

C'est mieux que readlink -e FILE o realpath car il fonctionne même si le fichier n'existe pas.

0 votes

Joli. Cela fonctionne également sur les fichiers/répertoires qui existent mais qui ne sont pas des liens symboliques.

0 votes

J'ai readlink disponible sur OS X 10.9 (Mavericks), donc c'est certainement la meilleure réponse ici.

6 votes

@KennethHoste : le -m n'est pas disponible sur Mavericks.

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X