GNU find inclui diretórios pai

2

Estou tentando fazer o GNU find excluir entradas ATÉ o nome do arquivo especificado.

Pegue esta árvore de amostra:

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

(Haveria um monte de outros arquivos no world e outros diretórios também, é por isso que eu não estou simplesmente procurando por hello.txt ).

Eu quero corresponder tudo, exceto "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
    
por elimirks 28.01.2014 / 17:04

2 respostas

1

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

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

Atualização:

Suponha que tenhamos um 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 as 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, poderemos criar uma expressão regular que corresponda a bits dela:

$ 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 negar o regex para obter o material 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
    
por 28.01.2014 / 17:24
0

Se você souber a profundidade exata da árvore (ou seja, você deseja obter os arquivos da terceira pasta em diante), poderá 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

Qual é exatamente o que você espera.

EDIT: isso deve ser melhor (mas mais feio!). Ele encontra o diretório em que test.txt está localizado e localiza todos os arquivos nele. A vantagem é que é completamente independente dos caminhos pai, ele irá automaticamente calculá-los.

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

A multilinha é melhor:

EXCLUDEFNAME="test.txt"
targetpath="$(find . -name "$EXCLUDEFNAME" -exec dirname {} \;)"
find "$targetpath" -mindepth 1 ! -name "$EXCLUDEFNAME"
    
por 28.01.2014 / 17:25

Tags