programas - programacion shell linux ejemplos
Eliminar parte de la ruta en Unix (7)
Estoy tratando de eliminar parte de la ruta en una cadena. Tengo el camino:
/path/to/file/drive/file/path/
Quiero eliminar la primera parte /path/to/file/drive
y producir el resultado:
file/path/
Nota: Tengo varias rutas en un ciclo while, con la misma /path/to/file/drive
en todas ellas, pero solo estoy buscando el ''cómo hacerlo'' para eliminar la cadena deseada.
Encontré algunos ejemplos, pero no puedo hacer que funcionen:
echo /path/to/file/drive/file/path/ | sed ''s:/path/to/file/drive:/2:''
echo /path/to/file/drive/file/path/ | sed ''s:/path/to/file/drive:2''
/2
es la segunda parte de la cadena y claramente estoy haciendo algo mal ... ¿tal vez hay una manera más fácil?
Pure bash, sin una codificación difícil de la respuesta
basenames()
{
local d="${2}"
for ((x=0; x<"${1}"; x++)); do
d="${d%/*}"
done
echo "${2#"${d}"/}"
}
- Argumento 1 : ¿Cuántos niveles desea mantener (2 en la pregunta original)
- Argumento 2 - El camino completo
Si desea eliminar las primeras N partes de la ruta , puede usar N llamadas a basename
, como en la respuesta de Glenn, pero probablemente sea más fácil usar globbing:
path=/path/to/file/drive/file/path/
echo "${path#*/*/*/*/*/}" # file/path/
Específicamente, ${path#*/*/*/*/*/}
significa "return $path
menos el prefijo más corto que contiene 5 barras diagonales" .
Si desea eliminar un cierto NÚMERO de componentes de ruta, debe usar cut
con -d''/''
. Por ejemplo, si path=/home/dude/some/deepish/dir
:
Para eliminar los primeros dos componentes:
# (Add 2 to the number of components to remove to get the value to pass to -f)
$ echo $path | cut -d''/'' -f4-
some/deepish/dir
Para mantener los primeros dos componentes:
$ echo $path | cut -d''/'' -f-3
/home/dude
Para eliminar los dos últimos componentes ( rev
invierte la cadena):
$ echo $path | rev | cut -d''/'' -f4- | rev
/home/dude/some
Para mantener los últimos tres componentes:
$ echo $path | rev | cut -d''/'' -f-3 | rev
some/deepish/dir
O bien, si desea eliminar todo antes de un componente en particular, sed
funcionaría:
$ echo $path | sed ''s/.*/(some/)//1/g''
some/deepish/dir
O después de un componente en particular:
$ echo $path | sed ''s//(dude/).*//1/g''
/home/dude
Es aún más fácil si no desea mantener el componente que está especificando:
$ echo $path | sed ''s/some.*//g''
/home/dude/
Y si quieres ser consistente, puedes hacer coincidir la barra final:
$ echo $path | sed ''s///some.*//g''
/home/dude
Por supuesto, si hace coincidir varias barras, debe cambiar el delimitador de sed
:
$ echo $path | sed ''s!/some.*!!g''
/home/dude
Tenga en cuenta que todos estos ejemplos usan rutas absolutas, tendrá que jugar para que funcionen con rutas relativas.
Si no quiere codificar la parte que está eliminando, haga lo siguiente:
$ s=''/path/to/file/drive/file/path/''
$ echo ${s#$(dirname "$(dirname "$s")")/}
file/path/
También puede usar la expansión de variable de shell POSIX para hacer esto.
path=/path/to/file/drive/file/path/
echo ${path#/path/to/file/drive/}
La parte #..
elimina una cadena principal que coincide cuando la variable se expande; esto es especialmente útil si sus cadenas ya están en variables de shell, como si estuviera usando un ciclo for
. También puede quitar cadenas coincidentes (por ejemplo, una extensión) desde el final de una variable, usando %...
Vea la página del hombre de bash
para los detalles sangrientos.
Una forma de hacer esto con sed es
echo /path/to/file/drive/file/path/ | sed ''s:^/path/to/file/drive/::''
Usar ${path#/path/to/file/drive/}
como lo sugiere mal otto es sin duda la mejor / típica forma de hacer esto, pero dado que hay muchas sugerencias sed, vale la pena señalar que sed es exagerado si eres trabajando con una cadena fija. También puedes hacer:
echo $PATH | cut -b 21-
Para descartar los primeros 20 caracteres. Del mismo modo, puede usar ${PATH:20}
en bash o $PATH[20,-1]
en zsh.