Comparación de carpetas

10

Tengo dos carpetas con estructuras de subcarpetas similares, que me gustaría comparar. Por ejemplo:

A 
├── child-1
├── child-2
├── child-3
├── child-4
├── child-5

y

B 
├── child-1-some-text
├── child-2-more-text
├── child-3-nothing
├── child-6-random-text
├── child-7-more-random-text

Me gustaría enumerar todas esas subcarpetas de las Acuales son prefijos para una subcarpeta By enumerar también las subcarpetas correspondientes B. La salida esperada es

child-1 -- child-1-some-text
child-2 -- child-2-more-text
child-3 -- child-3-nothing

Un requisito secundario: si hay varias coincidencias B, entonces debería dar un error / advertencia.

Mi solucion :

cd A
for f in `ls -d */`; 
do
    cd B;
    new_dirs=(`ls -1d $f*`);
    cd -;
    if [ ${#new_dirs[@]} -eq 0 ]
    then
        ## DO_Nothing
        continue;
    elif  [ ${#new_dirs[@]} -gt 1 ]
    then
        echo "Multiple matches to $f";
        continue;
    else
        echo "Unique Match found to $f -- ${new_dirs[0]}";
        continue;
    fi;    
done

Problema:

Para aquellos valores de $f, que no tienen subcarpetas correspondientes B, la construcción de la matriz me está dando un error. p.ej:

ls: no se puede acceder a 'child-4 *': no ​​existe tal archivo o directorio

Pregunta

  • ¿Cómo deshacerse de estos errores?
  • ¿Hay una mejor manera de lograr los objetivos que el que está en mi código?

¡Gracias por adelantado!

Mike VDC
fuente
44
¡+1 por proporcionar una solución casi funcional!
user5325
Esta no es una respuesta a su pregunta específica, pero puede usarla diff -rq DIR1 DIR2para comparar no solo la estructura de directorios, sino también el contenido de los archivos.
jrw32982 es compatible con Monica

Respuestas:

10

La mejor manera

No analizarls ; use globos en su lugar. De hecho, ya estás usando globos, simplemente envolviéndolos ls, lo cual no tiene sentido. Solo necesitas nullglobactivarlo cuando no hay coincidencias.

Evitar también cdsimplifica las cosas.

#!/bin/bash

shopt -s nullglob

dir1=A
dir2=B

for dir in "$dir1"/*/; do
    basename="$(basename -- "$dir")"
    dirs_match=( "$dir2/$basename"*/ )
    case ${#dirs_match[@]} in
    0)
        ;;
    1)
        echo "Unique match for $dir: ${dirs_match[*]}"
        ;;
    *)
        echo "Multiple matches for $dir: ${dirs_match[*]}" >&2
        ;;
    esac
done

Salida:

Unique match for A/child-1/: B/child-1-some-text/
Unique match for A/child-2/: B/child-2-more-text/
Multiple matches for A/child-3/: B/child-3-nothing/ B/child-3-something/

Agregué B/child-3-somethingpara probar el requisito secundario. Esto crea la estructura de directorios para probar:

mkdir -p A/child-{1..5} B/child-{1-some-text,2-more-text,3-nothing,3-something,6-random-text,7-more-random-text}

Por cierto, ShellCheck es muy útil para encontrar problemas en los scripts de shell.

wjandrea
fuente
ShellCheck.net es interesante, ¿sabe si carga todo a sus propios servidores o si todo se hace localmente? Solo me pregunto sobre la privacidad de la información ingresada. [Instalar el shellcheckpaquete sería lo más seguro]
Xen2050
@ Xen2050 Intenté desconectar mi Internet mientras estaba en el sitio, y parece que se está cargando. Me imagino que no lo mantiene, pero no estoy seguro. Y sí, el paquete es bueno; Yo uso un complemento Atom que lo usa.
wjandrea
Gracias por las sugerencias Y también muchísimas gracias por apuntar hacia ShellCheck. ¡Me encantó la parte en la que no solo te dice tus errores, sino que también te da sugerencias! @ Xen2050, sobre la parte de carga, acabo de instalar shellcheckusando apty luego deshabilité la red. Parece estar funcionando sin internet .
Mike VDC
2

Llamar lsa una carpeta inexistente arroja el mensaje de error que encontró. La manera más fácil es simplemente ignorar esto mediante la sustitución de la línea 5 en el script con esto: new_dirs=(`ls -1d $f* 2> /dev/null`);.

cauon
fuente
¿Has probado esto? Stderr parece ser ignorado por defecto, cuando ejecuto t=(`echo ok; echo err 1>&2`)$ t (o ${t[@]}) solo contiene ok, err se ve en la terminal pero no se guarda de todos modos. ¿O hay algo gracioso en mi examen?
Xen2050