web-dev-qa-db-fra.com

Comment obtenir le répertoire absolu d'un fichier dans bash?

J'ai écrit un script bash qui prend un fichier d'entrée en argument et le lit.
Ce fichier contient des chemins (par rapport à son emplacement) vers les fichiers supplémentaires utilisés.

J'aimerais que le script aille dans le dossier contenant le fichier d'entrée pour exécuter d'autres commandes.

Donc, comment puis-je obtenir le dossier (et juste le dossier) à partir d'un fichier d'entrée? (In linux.)

69
BobMcGee

Pour obtenir le chemin complet, utilisez:

readlink -f relative/path/to/file

Pour obtenir le répertoire d'un fichier:

dirname relative/path/to/file

Vous pouvez également combiner les deux:

dirname $(readlink -f relative/path/to/file)

Si readlink -f n'est pas disponible sur votre système, vous pouvez l'utiliser*:

function myreadlink() {
  (
  cd "$(dirname $1)"         # or  cd "${1%/*}"
  echo "$PWD/$(basename $1)" # or  echo "$PWD/${1##*/}"
  )
}

Notez que si vous avez seulement besoin de vous déplacer vers un répertoire d'un fichier spécifié comme chemin relatif, vous n'avez pas besoin de connaître le chemin absolu, un chemin relatif est parfaitement légal, utilisez donc simplement:

cd $(dirname relative/path/to/file)

si vous souhaitez revenir au chemin d'origine (pendant l'exécution du script), utilisez pushd au lieu de cd et popd lorsque vous avez terminé.


* Bien que myreadlink ci-dessus soit suffisant dans le contexte de cette question, il présente certaines limitations par rapport à l'outil readlink suggéré ci-dessus. Par exemple, il ne suit pas correctement un lien vers un fichier avec différents basename.

134
Chen Levy

Jetez un coup d’œil à la page de manuel de realpath, j’utilise cela et quelque chose comme:

CONTAININGDIR = $ (realpath $ {FILEPATH%/*})

faire ce que vous essayez de faire.

18
Richard Sitze

Cela fonctionnera à la fois pour le fichier et le dossier:

absPath(){
    if [[ -d "$1" ]]; then
        cd "$1"
        echo "$(pwd -P)"
    else 
        cd "$(dirname "$1")"
        echo "$(pwd -P)/$(basename "$1")"
    fi
}
6
Jahid
$cat abs.sh
#!/bin/bash
echo "$(cd "$(dirname "$1")"; pwd -P)"

Quelques explications:

  1. Ce script obtient un chemin relatif en argument "$1"
  2. Ensuite, nous obtenons dirname une partie de ce chemin (vous pouvez transmettre soit dir, soit fichier à ce script): dirname "$1"
  3. Puis nous cd "$(dirname "$1"); dans ce répertoire relatif
  4. pwd -P Et obtenez le chemin absolu. L'option -P Évitera les liens symboliques
  5. En dernière étape, nous echo cela

Ensuite, lancez votre script:

abs.sh your_file.txt
3
Eugen Konkov

Essayez notre nouveau produit de bibliothèque Bash realpath-lib sur GitHub que nous avons donné à la communauté pour une utilisation gratuite et sans entrave. C'est propre, simple et bien documenté, il est donc formidable d'apprendre. Tu peux faire:

get_realpath <absolute|relative|symlink|local file path>

Cette fonction est le noyau de la bibliothèque:

if [[ -f "$1" ]]
then
    # file *must* exist
    if cd "$(echo "${1%/*}")" &>/dev/null
    then
        # file *may* not be local
        # exception is ./file.ext
        # try 'cd .; cd -;' *works!*
        local tmppwd="$PWD"
        cd - &>/dev/null
    else
        # file *must* be local
        local tmppwd="$PWD"
    fi
else
    # file *cannot* exist
    return 1 # failure
fi

# reassemble realpath
echo "$tmppwd"/"${1##*/}"
return 0 # success

}

C'est Bash 4+, ne nécessite aucune dépendance et fournit également get_dirname, get_filename, get_stemname et validate_path.

1
AsymLabs

Le problème avec la réponse ci-dessus vient avec les fichiers saisis avec "./" comme "./my-file.txt"

Contournement (de plusieurs):

    myfile="./somefile.txt"
    FOLDER="$(dirname $(readlink -f "${ARG}"))"
    echo ${FOLDER}
0
Mike Q