script programas programacion operaciones manejo ejemplos comandos comando cadenas aritmeticas shell unix scripting sed

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.