Ottieni il percorso della directory del file dal percorso del file


400

In Bash, se VAR="/home/me/mydir/file.c", come posso ottenere "/home/me/mydir"?

Risposte:


649

dirnamee basenamesono gli strumenti che stai cercando per estrarre i componenti del percorso:

$ VAR=/home/me/mydir/file.c

$ DIR=$(dirname "${VAR}")

$ echo "${DIR}"
/home/me/mydir

$ basename "${VAR}"
file.c

Non sono comandi interni di Bash ma fanno parte dello standard POSIX (vedi dirname, basename) e quindi dovrebbero essere disponibili nella stragrande maggioranza dei sistemi che eseguiranno Bash.


4
Perché l'uso delle parentesi attorno ai nomi delle variabili e non "$ VAR" per esempio?
— user658182

1
stackoverflow.com/questions/8748831/… risponde alla domanda sopra.
— user658182

1
@ user658182 In questo esempio particolare, è fatto per abitudine, non per necessità.
— Carrello abbandonato

95
$ export VAR=/home/me/mydir/file.c
$ export DIR=${VAR%/*}
$ echo "${DIR}"
/home/me/mydir

$ echo "${VAR##*/}"
file.c

Per evitare la dipendenza con basenameedirname


3
Poiché entrambi fanno parte di POSIX, la dipendenza non dovrebbe costituire un problema.
— orkoden,

1
orkoden, hai ragione. Lo scopo della mia risposta è mostrare che non vi è alcun obbligo di eseguire due ulteriori processi. bash è autosufficiente per il caso d'uso.
— Emmanuel Devaux,

2
Sto usando il metodo Emmanuel perché desidero passare un nome di file o di cartella, quindi calcolare il percorso della cartella. L'uso di questo regex fa la cosa giusta, mentre la funzione dirname ha restituito la cartella principale quando ho inserito una cartella.
— AnneTheAgile,

8
Tuttavia, se non ci sono informazioni sul percorso in $ VAR, $ {VAR% / *} / test produce un valore imprevisto pari a $ VAR / test mentre $ (nome dir $ VAR) produrrà il valore più prevedibile e appropriato di ./test. Questo è un grosso problema perché il primo tenterà di trattare il nome del file come una directory mentre il secondo sarà OK.
— davemyron,

19

In una nota correlata, se hai solo il nome file o il percorso relativo, dirnameda solo non aiuterà. Per me, la risposta è stata readlink.

fname='txtfile'    
echo $(dirname "$fname")                # output: .
echo $(readlink -f "$fname")            # output: /home/me/work/txtfile

È quindi possibile combinare i due per ottenere solo la directory.

echo $(dirname $(readlink -f "$fname")) # output: /home/me/work

1
se non esiste più di un componente del percorso, è necessario utilizzare readlink -m "$fname"per canonicalizzare ricorsivamente il nome dato
— EDkan

7

Se ti interessa che i file di destinazione siano link simbolici, in primo luogo puoi controllarli e ottenere il file originale. La clausola if di seguito può aiutarti.

if [ -h $file ]
then
 base=$(dirname $(readlink $file))
else
 base=$(dirname $file)
fi

5

Ci stavo giocando e ho trovato un'alternativa.

$ VAR=/home/me/mydir/file.c

$ DIR=`echo $VAR |xargs dirname`

$ echo $DIR
/home/me/mydir

La parte che mi è piaciuta è che è stato facile estendere il backup dell'albero:

$ DIR=`echo $VAR |xargs dirname |xargs dirname |xargs dirname`

$ echo $DIR
/home

1

Ecco uno script che ho usato per il taglio ricorsivo. Sostituisci $ 1 con la directory che desideri, ovviamente.

BASEDIR="$1"
IFS=$'\n'
cd $BASEDIR
 for f in $(find . -type f -name ' *')
 do 
    DIR=$(dirname "$f")
    DIR=${DIR:1}
    cd $BASEDIR$DIR
    rename 's/^ *//' *
 done

0

Innanzitutto, ho sostituito /con spazio vuoto ( ). Quindi, ho eliminato tutti i caratteri prima di qualsiasi spazio vuoto ( ). Alla fine, ho rimosso il primo personaggio che è spazio vuoto ( ).

$ VAR="/home/me/mydir/file.c"

$ echo $VAR | tr '/' ' ' | sed 's/^.* / /' | cut -c2-
file.c

0
HERE=$(cd $(dirname $BASH_SOURCE) && pwd)

dove ottieni il percorso completo con new_path = $(dirname ${BASH_SOURCE[0]}). Si modifica la directory corrente con cd new_path e quindi si esegue pwdper ottenere il percorso completo della directory corrente.

Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.