Si tengo una ruta de archivo como ...
/home/smith/Desktop/Test
/home/smith/Desktop/Test/
¿Cómo cambio la cadena para que sea el directorio principal?
p.ej
/home/smith/Desktop
/home/smith/Desktop/
Si tengo una ruta de archivo como ...
/home/smith/Desktop/Test
/home/smith/Desktop/Test/
¿Cómo cambio la cadena para que sea el directorio principal?
p.ej
/home/smith/Desktop
/home/smith/Desktop/
Respuestas:
dir=/home/smith/Desktop/Test
parentdir="$(dirname "$dir")"
Funciona si también hay una barra inclinada final.
parentdir=$(dirname `pwd`)
... pero lo que se "ve aquí " está roto. Aquí está la solución:
> pwd
/home/me
> x='Om Namah Shivaya'
> mkdir "$x" && cd "$x"
/home/me/Om Namah Shivaya
> parentdir="$(dirname "$(pwd)")"
> echo $parentdir
/home/me
Solo utilícelo echo $(cd ../ && pwd)
mientras trabaja en el directorio cuyo directorio principal desea averiguar. Esta cadena también tiene el beneficio adicional de no tener barras diagonales finales.
echo
aquí.
Claramente, el directorio principal se proporciona simplemente agregando el nombre de archivo punto-punto:
/home/smith/Desktop/Test/.. # unresolved path
Pero debe querer la ruta resuelta (una ruta absoluta sin ningún componente de ruta punto-punto):
/home/smith/Desktop # resolved path
El problema con las respuestas principales que usan dirname
es que no funcionan cuando ingresas una ruta con puntos-puntos:
$ dir=~/Library/../Desktop/../..
$ parentdir="$(dirname "$dir")"
$ echo $parentdir
/Users/username/Library/../Desktop/.. # not fully resolved
Esto es más poderoso :
dir=/home/smith/Desktop/Test
parentdir=`eval "cd $dir;pwd;cd - > /dev/null"`
Puede alimentarlo /home/smith/Desktop/Test/..
, pero también rutas más complejas como:
$ dir=~/Library/../Desktop/../..
$ parentdir=`eval "cd $dir;pwd;cd - > /dev/null"`
$ echo $parentdir
/Users # the fully resolved path!
EDITAR: Si no funciona, verifique que cd
no se haya modificado, como a veces es una práctica común,
$ which cd
cd is a function #cd was modified to print extra info, so use "builtin cd" to override
cd ()
{
builtin cd "$@";
ls -FGAhp
}
...
eval
NO es excelente si hay alguna posibilidad de analizar la entrada del usuario que podría ubicarlo en un lugar que no espera o ejecutar cosas malas contra su sistema. ¿Se puede usar en pushd $dir 2>&1 >/dev/null && pwd && popd 2>&1 >/dev/null
lugar de la eval
?
eval
nada: solo hazlo parentdir=$(cd -- "$dir" && pwd)
. Como cd
se ejecuta en una subshell, no es necesario cd
volver a donde estábamos. El --
está aquí en caso de que la expansión de $dir
comience con un guión. Esto &&
es solo para evitar parentdir
tener un contenido no vacío cuando cd
no tuvo éxito.
Me gusta el código muy corto, claro y garantizado. Punto de bonificación si no ejecuta un programa externo, ya que el día que necesite procesar una gran cantidad de entradas, será notablemente más rápido.
No estoy seguro de qué garantías tiene y quiere, por lo que ofrece de todos modos.
Si tiene garantías, puede hacerlo con un código muy corto. La idea es usar la función de sustitución de texto bash para cortar la última barra y lo que sigue.
Responda de casos simples a más complejos de la pregunta original.
P=/home/smith/Desktop/Test ; echo "${P%/*}"
/home/smith/Desktop
P=/home/smith/Desktop/Test/ ; echo "${P%/*/}/"
/home/smith/Desktop/
for P in \
/home/smith/Desktop/Test \
/home/smith/Desktop/Test/
do
P_ENDNOSLASH="${P%/}" ; echo "${P_ENDNOSLASH%/*}"
done
/home/smith/Desktop
/home/smith/Desktop
for P in \
/home/smith/Desktop/Test \
/home/smith/Desktop/Test/ \
/home/smith///Desktop////Test//
do
P_NODUPSLASH="${P//\/*(\/)/\/}"
P_ENDNOSLASH="${P_NODUPSLASH%%/}"
echo "${P_ENDNOSLASH%/*}";
done
/home/smith/Desktop
/home/smith/Desktop
/home/smith/Desktop
${BASH_SOURCE[0]}
cual sería la ruta completa al script si no se obtuvo a través de source
o .
.
bash: dirname 'Test': syntax error: invalid arithmetic operator (error token is "'Test'")
. El código vinculado también está mal.
dirname Test
desde el directorio Test
está en.
Dependiendo de si necesita rutas absolutas, es posible que desee dar un paso adicional:
child='/home/smith/Desktop/Test/'
parent=$(dirname "$child")
abs_parent=$(realpath "$parent")
usa esto: export MYVAR="$(dirname "$(dirname "$(dirname "$(dirname $PWD)")")")"
si quieres el 4to directorio padre
export MYVAR="$(dirname "$(dirname "$(dirname $PWD)")")"
si quieres el tercer directorio padre
export MYVAR="$(dirname "$(dirname $PWD)")"
si quieres el segundo directorio padre
feo pero eficiente
function Parentdir()
{
local lookFor_ parent_ switch_ i_
lookFor_="$1"
#if it is not a file, we need the grand parent
[ -f "$lookFor_" ] || switch_="/.."
#length of search string
i_="${#lookFor_}"
#remove string one by one until it make sens for the system
while [ "$i_" -ge 0 ] && [ ! -d "${lookFor_:0:$i_}" ];
do
let i_--
done
#get real path
parent_="$(realpath "${lookFor_:0:$i_}$switch_")"
#done
echo "
lookFor_: $1
{lookFor_:0:$i_}: ${lookFor_:0:$i_}
realpath {lookFor_:0:$i_}: $(realpath ${lookFor_:0:$i_})
parent_: $parent_
"
}
lookFor_: /home/Om Namah Shivaya
{lookFor_:0:6}: /home/
realpath {lookFor_:0:6}: /home
parent_: /home
lookFor_: /var/log
{lookFor_:0:8}: /var/log
realpath {lookFor_:0:8}: /UNIONFS/var/log
parent_: /UNIONFS/var
lookFor_: /var/log/
{lookFor_:0:9}: /var/log/
realpath {lookFor_:0:9}: /UNIONFS/var/log
parent_: /UNIONFS/var
lookFor_: /tmp//res.log/..
{lookFor_:0:6}: /tmp//
realpath {lookFor_:0:6}: /tmp
parent_: /
lookFor_: /media/sdc8/../sdc8/Debian_Master//a
{lookFor_:0:35}: /media/sdc8/../sdc8/Debian_Master//
realpath {lookFor_:0:35}: /media/sdc8/Debian_Master
parent_: /media/sdc8
lookFor_: /media/sdc8//Debian_Master/../Debian_Master/a
{lookFor_:0:44}: /media/sdc8//Debian_Master/../Debian_Master/
realpath {lookFor_:0:44}: /media/sdc8/Debian_Master
parent_: /media/sdc8
lookFor_: /media/sdc8/Debian_Master/../Debian_Master/For_Debian
{lookFor_:0:53}: /media/sdc8/Debian_Master/../Debian_Master/For_Debian
realpath {lookFor_:0:53}: /media/sdc8/Debian_Master/For_Debian
parent_: /media/sdc8/Debian_Master
lookFor_: /tmp/../res.log
{lookFor_:0:8}: /tmp/../
realpath {lookFor_:0:8}: /
parent_: /
Comenzó a partir de la idea / comentario Charles Duffy - 17 de diciembre de 2014 a las 5:32 sobre el tema Obtener el nombre del directorio actual (sin ruta completa) en un script Bash
#!/bin/bash
#INFO : /programming/1371261/get-current-directory-name-without-full-path-in-a-bash-script
# comment : by Charles Duffy - Dec 17 '14 at 5:32
# at the beginning :
declare -a dirName[]
function getDirNames(){
dirNr="$( IFS=/ read -r -a dirs <<<"${dirTree}"; printf '%s\n' "$((${#dirs[@]} - 1))" )"
for(( cnt=0 ; cnt < ${dirNr} ; cnt++))
do
dirName[$cnt]="$( IFS=/ read -r -a dirs <<<"$PWD"; printf '%s\n' "${dirs[${#dirs[@]} - $(( $cnt+1))]}" )"
#information – feedback
echo "$cnt : ${dirName[$cnt]}"
done
}
dirTree=$PWD;
getDirNames;
Si por cualquier razón usted está interesado en la navegación de un número específico de directorios también se puede hacer: nth_path=$(cd "$( dirname "${BASH_SOURCE[0]}" )" >/dev/null 2>&1 && cd ../../../ && pwd)
. Esto daría 3 directorios de padres arriba
..
', pero tal vez eso no sea exactamente lo que tenía en mente.