GNU find inclui diretórios pai

GNU find inclui diretórios pai

Estou tentando fazer com que o GNU encontre entradas excluídas ATÉ o nome de arquivo especificado.

Veja este exemplo de árvore:

./foo
./foo/another.txt
./foo/bar
./foo/bar/world
./foo/bar/world/test.txt
./foo/bar/world/hello.txt

(Haveria vários outros arquivos no worlde em outros diretórios também, é por isso que não estou simplesmente procurando por hello.txt).

Quero corresponder tudo, menos 'test.txt' e seus diretórios pai.

A saída deve ser simplesmente foo/bar/world/hello.txt.

Este comando produz os resultados corretos, mas é bastante confuso e produziria resultados errados se houvesse vários diretórios com os mesmos nomes:

find * ! -name test.txt -a ! -name foo -a ! -name bar -a ! -name world

Responder1

Diga que findvocê está interessado apenas em arquivos, não em diretórios.

find ./foo -type f ! -name test.txt

Atualizar:

Suponha que tenhamos este exemplo um pouco mais complexo:

$ 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

Se o seu objetivo é excluir coisas, você precisa especificar -depthpara que os arquivos sejam vistos antes de seus diretórios:

$ 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

Se você souber o caminho que deseja manter, podemos criar uma expressão regular que corresponda a partes dele:

$ find ./foo -depth -regextype posix-extended -regex '^\./foo(/bar(/world(/test.txt)?)?)?'
./foo/bar/world/test.txt
./foo/bar/world
./foo/bar
./foo

Então podemos simplesmente negar o regex para obter o que você deseja remover:

$ 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

Responder2

Se você sabe a profundidade exata da árvore (ou seja, deseja obter os arquivos da terceira pasta em diante), você pode usar:

find . -mindepth $depth ! -name test.txt

Com sua estrutura de diretórios, recebo:

$ find . -mindepth 4 ! -name test.txt
./foo/bar/world/hello.txt

O que é exatamente o que você espera.


EDIT: isso deveria ser melhor (mas mais feio!). Ele encontra o diretório onde test.txtestá localizado e todos os arquivos nele contidos. A vantagem é que é completamente independente dos caminhos pais, irá calculá-los automaticamente.

EXCLUDEFNAME="test.txt"; find $(find . -name "$EXCLUDEFNAME" -exec dirname {} \; -quit) -mindepth 1 ! -name "$EXCLUDEFNAME"

Multilinha é melhor:

EXCLUDEFNAME="test.txt"
targetpath="$(find . -name "$EXCLUDEFNAME" -exec dirname {} \;)"
find "$targetpath" -mindepth 1 ! -name "$EXCLUDEFNAME"

informação relacionada