
Estoy intentando que GNU encuentre entradas excluidas HASTA el nombre de archivo especificado.
Tome este árbol de muestra:
./foo
./foo/another.txt
./foo/bar
./foo/bar/world
./foo/bar/world/test.txt
./foo/bar/world/hello.txt
(Habría muchos otros archivos en los world
directorios y otros también, es por eso que no estoy simplemente buscando hello.txt
).
Quiero que coincida con todo menos con 'test.txt' y sus directorios principales.
La salida debería ser simplemente foo/bar/world/hello.txt
.
Este comando produce los resultados correctos, pero es bastante complicado y produciría resultados incorrectos si hubiera varios directorios con los mismos nombres:
find * ! -name test.txt -a ! -name foo -a ! -name bar -a ! -name world
Respuesta1
Dígale find
que solo le interesan los archivos, no los directorios.
find ./foo -type f ! -name test.txt
Actualizar:
Supongamos que tenemos este ejemplo un poco más complejo:
$ find ./foo
./foo
./foo/baz
./foo/baz/b.csv
./foo/baz/a.txt
./foo/bar
./foo/bar/c.txt
./foo/bar/world
./foo/bar/world/hello.txt
./foo/bar/world/test.txt
Si su objetivo es eliminar cosas, debe especificar -depth
que los archivos se vean antes que sus directorios:
$ find ./foo -depth
./foo/baz/b.csv
./foo/baz/a.txt
./foo/baz
./foo/bar/c.txt
./foo/bar/world/hello.txt
./foo/bar/world/test.txt
./foo/bar/world
./foo/bar
./foo
Si conoce la ruta que desea conservar, podemos diseñar una expresión regular que coincida con partes de ella:
$ find ./foo -depth -regextype posix-extended -regex '^\./foo(/bar(/world(/test.txt)?)?)?'
./foo/bar/world/test.txt
./foo/bar/world
./foo/bar
./foo
Luego podemos simplemente negar la expresión regular para obtener lo que deseas eliminar:
$ find ./foo -depth -regextype posix-extended ! -regex '^\./foo(/bar(/world(/test.txt)?)?)?'
./foo/baz/b.csv
./foo/baz/a.txt
./foo/baz
./foo/bar/c.txt
./foo/bar/world/hello.txt
Respuesta2
Si conoce la profundidad exacta del árbol (es decir, desea obtener los archivos desde la tercera carpeta en adelante), puede usar:
find . -mindepth $depth ! -name test.txt
Con su estructura de directorio, obtengo:
$ find . -mindepth 4 ! -name test.txt
./foo/bar/world/hello.txt
Que es exactamente lo que esperas.
EDITAR: esto debería ser mejor (¡pero más feo!). Encuentra el directorio donde test.txt
se encuentra y encuentra todos los archivos que contiene. La ventaja es que es completamente independiente de las rutas principales, las calculará automáticamente.
EXCLUDEFNAME="test.txt"; find $(find . -name "$EXCLUDEFNAME" -exec dirname {} \; -quit) -mindepth 1 ! -name "$EXCLUDEFNAME"
Multilínea es mejor:
EXCLUDEFNAME="test.txt"
targetpath="$(find . -name "$EXCLUDEFNAME" -exec dirname {} \;)"
find "$targetpath" -mindepth 1 ! -name "$EXCLUDEFNAME"