Tengo cadenas que inicialmente contienen diferentes rutas de directorio, donde tanto el segundo como el segundo último subdirectorio pueden variar en longitud, así
/home/Leo/Work/CMI/ARCH/MWS/Disks /home/Cleo/Work/CMI/ARCH/BK/DisksQuiero recortar los primeros 5 subdirectorios y mostrar solo los últimos 2, así
echo "/MWS/Disks" echo "/BK/Disks"Una forma de recortar los primeros 5 subdirectorios de las cadenas iniciales podría ser desplazar a la izquierda cada carácter hasta que ambas cadenas comiencen con el penúltimo '/'.
La Guía para principiantes de Bash describe un shift built-in la izquierda los parámetros posicionales en un comando y descarta los argumentos no utilizados. Pero no es inmediatamente obvio si esto podría usarse para recortar los primeros 5 subdirectorios de las cadenas descritas anteriormente.
En Bash, ¿cómo reduzco estas cadenas, preferiblemente sin usar bucles?
ACLARACIÓN
A juzgar por los comentarios, se necesita un poco más de contexto. My Bash script recupera archivos Mdos y Qdos históricos de imágenes de disquete de 8 pulgadas y guarda archivos en directorios en el disco duro.
Para bien o para mal, creé un esquema personalizado que almacena las rutas de los directorios usando nombres de variables de 3 caracteres donde cada nombre es un acrónimo de la sección de la ruta al directorio actual.
Por ejemplo, MWC es un acrónimo de $MY/Work/CMI en la siguiente ruta
MY="$USER" MWC="C:/cygwin64/home/$MY/Work/CMI" cd "$MWC" pwd C:/cygwin64/home/$MY/Work/CMIDel mismo modo, las variables de 3 caracteres apuntan al siguiente subdirectorio más arriba en el árbol
WCA="$MWC/ARCH" es decir C:/cygwin64/home/$MY/Work/CMI/ARCH , ruta a una galería de propietarios de archivos.
A medida que las rutas de directorio se alargan, las variables de 3 caracteres hacen que las rutas se identifiquen fácilmente al conservar los espacios en blanco en la lista. Sin embargo, la ruta completa aparece cada vez que mi script hace referencia a una ruta. De ahí la necesidad de recortar partes de la cadena que no tienen interés para el usuario final.
Si el número de subdirectorios es siempre el mismo, puede usar la expansión de parámetros para eliminar los primeros 5 subdirectorios:
s=/home/Leo/Work/CMI/ARCH/MWS/Disks s=/${s#/*/*/*/*/*/} echo $s # /MWS/DisksO, si sabe que necesita las dos últimas partes sea cual sea la profundidad del camino:
s=/home/Leo/Work/CMI/ARCH/MWS/Disks last=/${s##*/} last_but1=${s%$last} last_but1=/${last_but1##*/} echo $last_but1$last # /MWS/Disks${s#PATTERN} elimina PATTERN del final de $s .${s%PATTERN} elimina PATTERN desde el principio de $s .# o % , se encuentra la coincidencia más corta de PATRÓN. Doblarlos hace que el partido sea lo más largo posible.Como alternativa a la expansión de parámetros, puede utilizar el operador =~ :
dir='/home/Leo/Work/CMI/ARCH/MWS/Disks' [[ $dir =~ /[^/]*/[^/]*$ ]] && echo "${BASH_REMATCH[0]}"Suponiendo que las entradas provienen de un archivo (o se transmiten/canalizan desde otro proceso del sistema operativo) ...
Ejemplo de entrada:
$ cat dir.file /home/Leo/Work/CMI/ARCH/MWS/Disks /home/Cleo/Work/CMI/ARCH/BK/Disks Una idea awk :
awk 'BEGIN {FS=OFS="/"} {print OFS $(NF-1),$(NF)}' dir.fileEsto genera:
/MWS/Disks /BK/Disks Si los resultados deben almacenarse para su uso posterior, no debería ser demasiado difícil agregar código según sea necesario (por ejemplo, redirigir a un archivo, canalizar a otro proceso, pasar como entrada a un ciclo while/read , cargar en una matriz , etc).
Si OP está procesando estas cadenas una a la vez (por ejemplo, como una variable en un bucle), probablemente me quede con una solución de sustitución de parámetros (vea la respuesta de choroba) que no requiere ningún gasto general para generar subprocesos.