Cómo obtener la última parte de dirname en Bash

81

Supongamos que tengo un archivo /from/here/to/there.txty quiero obtener solo la última parte de su nombre de directorio en tolugar de /from/here/to, ¿qué debo hacer?

berenjena
fuente

Respuestas:

120

Puede usar basenameaunque no sea un archivo. Quite el nombre del archivo usando dirname, luego use basenamepara obtener el último elemento de la cadena:

dir="/from/here/to/there.txt"
dir="$(dirname $dir)"   # Returns "/from/here/to"
dir="$(basename $dir)"  # Returns just "to"
David W.
fuente
2
el comando '$ dir = "$ (dirname $ dir)"' no funciona para mí, pero 'dir = "$ (dirname $ dir)"' funciona bien.
Nikolai Saiko
2
No debería haber tenido el dólar al frente dircuando lo configuro.
David W.
26

Lo contrario de dirnamees basename:

basename "$(dirname "/from/here/to/there.txt")"
ese otro chico
fuente
23

Usando bashfunciones de cadena:

$ s="/from/here/to/there.txt"
$ s="${s%/*}" && echo "${s##*/}"
to
Jaypal Singh
fuente
9

Usando la expansión del parámetro Bash , puede hacer esto:

path="/from/here/to/there.txt"
dir="${path%/*}"       # sets dir      to '/from/here/to' (equivalent of dirname)
last_dir="${dir##*/}"  # sets last_dir to 'to' (equivalent of basename)

Esto es más eficiente ya que no se utilizan comandos externos.

codeforester
fuente
Acabo de probar esto. En FreeBSD, aquí están mis resultados: Código: #! / Bin / sh cd / var / svn / repos path = "$ 1" echo "$ {path}" dir = "$ {path% / *}" echo "$ {dir } "actual =" $ {dir ## * /} "echo" $ {actual} "----------------------------- ----------- Resultados: $ ./makerepo.sh / var / test / var / test / var var $ ------------------- ----------------- ¡Fallar! Lo siento. Parecía un buen método pero no una respuesta correcta.
Richard Robertson
4

Manera pura BASH:

s="/from/here/to/there.txt"
[[ "$s" =~ ([^/]+)/[^/]+$ ]] && echo "${BASH_REMATCH[1]}"
to
anubhava
fuente
2
No funcionará si el archivo no tiene punto .. No funcionará si el directorio tiene un punto .. Manténgalo simple y use la barra /como delimitador.
alvits
1
Muchas gracias @Akshay
anubhava
3

Una awkforma de hacerlo sería:

awk -F'/' '{print $(NF-1)}' <<< "/from/here/to/there.txt"

Explicación:

  • -F'/' establece el separador de campo como "/"
  • imprimir el penúltimo campo $(NF-1)
  • <<<usa cualquier cosa después de ella como entrada estándar ( explicación wiki )
csiu
fuente
2

Una forma mas

IFS=/ read -ra x <<<"/from/here/to/there.txt" && printf "%s\n" "${x[-2]}"
iruvar
fuente
Más fácil de usar: printf "%s\n" "${x[-2]}".
gniourf_gniourf
1

Esta pregunta es algo como ESTO .

Para resolver eso puedes hacer:

DirPath="/from/here/to/there.txt"
DirPath="$(dirname $DirPath)"
DirPath="$(basename $DirPath)"

echo "$DirPath"

Como dijo mi amigo, esto también es posible:

basename `dirname "/from/here/to/there.txt"`

Para obtener cualquier parte de su camino, puede hacer:

echo "/from/here/to/there.txt" | awk -F/ '{ print $2 }'
OR
echo "/from/here/to/there.txt" | awk -F/ '{ print $3 }'
OR
etc
MLSC
fuente
1

La respuesta principal es absolutamente correcta para la pregunta formulada. En un caso más genérico con el directorio necesario en medio de una ruta larga, este enfoque conduce a un código difícil de leer. Por ejemplo :

dir="/very/long/path/where/THIS/needs/to/be/extracted/text.txt"
dir="$(dirname $dir)"
dir="$(dirname $dir)"
dir="$(dirname $dir)"
dir="$(dirname $dir)"
dir="$(dirname $dir)"
dir="$(basename $dir)"

En este caso se puede utilizar:

IFS=/; set -- "/very/long/path/where/THIS/needs/to/be/extracted/text.txt"; set $1; echo $6
THIS
yashma
fuente