2013-07-10 16 views
61

Ho scritto uno script bash che prende un file di input come argomento e lo legge.
Questo file contiene alcuni percorsi (relativi alla posizione) ai file aggiuntivi utilizzati.Come si ottiene la directory assoluta di un file in bash?

vorrei lo script per passare alla cartella contenente il file di input, per eseguire ulteriori comandi.

Così, come faccio ad ottenere la cartella (e solo la cartella) da un file di input? (in Linux.)

+0

State dando il percorso completo del file di input o solo il percorso relativo alla corrente directory di lavoro? – dmh

+0

dhm: l'input fornisce il percorso relativo, voglio il percorso assoluto * meno * nomefile. – BobMcGee

risposta

121

Per ottenere l'uso percorso completo:

readlink -f relative/path/to/file 

Per ottenere la directory di un file:

dirname relative/path/to/file 

È inoltre possibile combinare le due cose:

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

Se readlink -f non è disponibile sul sistema è possibile utilizzare questo:

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

Nota che se avete solo bisogno di passare a una directory di un file specificato come percorso relativo, non è necessario conoscere il percorso assoluto, un percorso relativo è perfettamente legale, quindi basta usare:

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

se si vuole tornare indietro (mentre lo script è in esecuzione) per il percorso originale, utilizzare pushd invece di cd, e popd quando si è fatto.

+10

Si noti che 'readlink -f' non funziona su OS X, sfortunatamente. –

+0

Non voglio l'intero percorso, voglio solo una cartella. Ma questo offre abbastanza per essere utile: readlink -f relativaFileLocation | xargs dirname – BobMcGee

+1

@EmilSit: hai ragione - nativamente. Ma puoi 'preparare installare coreutils' per ottenerlo. http://stackoverflow.com/a/4031502/1022967. – mpettis

0

Sono stato con readlink -f funziona su Linux

così

FULL_PATH=$(readlink -f filename) 
DIR=$(dirname $FULL_PATH) 

PWD=$(pwd) 

cd $DIR 

#<do more work> 

cd $PWD 
+3

non usare nomi di variabili maiuscole in Bash, un giorno si scontrerà con variabili già esistenti ... oh, e questo giorno è ora: sapevi che la variabile 'PWD' esiste già in Bash e il suo valore è in realtà la directory corrente? E usa anche più citazioni. –

+0

Grazie mille, lo terrò a mente. –

17

Date un'occhiata alla pagina man per realpath, io uso questo e qualcosa di simile:

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

to fai quello che sembra stia cercando di fare.

+0

realpath fa uno strano per me dove risolve i collegamenti simbolici di dirs relativi –

+0

Grazie! Ha funzionato per me su Mac OS –

1

Prova il nostro nuovo prodotto di libreria Bash realpath-lib su GitHub che abbiamo fornito alla comunità per l'utilizzo gratuito e senza impedimenti. È pulito, semplice e ben documentato, quindi è bello imparare da. Si può fare:

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

Questa funzione è il nucleo della biblioteca:

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 

} 

E 'Bash 4+, non richiede alcuna dipendenza e fornisce anche get_dirname, get_filename, get_stemname e validate_path.

0

un problema con la risposta di cui sopra viene fornito con i file di input con "./" come" ./my-file.txt"

Soluzione alternativa (di molti):

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

Questo funziona sia per file e cartelle:

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

Alcune spiegazioni:

  1. Questo script ottenere percorso relativo come argomento "$1"
  2. allora otteniamo nomedir parte di quel percorso (è possibile passare sia dir o il file da questo script): dirname "$1"
  3. Poi abbiamo cd "$(dirname "$1"); in questa relativa dir
  4. pwd -P e ottenere percorso assoluto. L'opzione -P eviterà i collegamenti simbolici
  5. Come ultimo passo abbiamo echo che

Quindi eseguire lo script:

abs.sh your_file.txt 
Problemi correlati