
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 world
e 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 find
você 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 -depth
para 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.txt
está 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"