Veja como você pode especificar isso com find
:
find . -type f -name "*_peaks.bed" ! -path "./tmp/*" ! -path "./scripts/*"
Explicação:
find .
- Comece a encontrar a partir do diretório de trabalho atual (recursivamente por padrão)
-type f
- Especifique find
que você deseja apenas arquivos nos resultados
-name "*_peaks.bed"
- Procure por arquivos com o nome terminando em _peaks.bed
! -path "./tmp/*"
- Exclua todos os resultados cujo caminho comece com ./tmp/
! -path "./scripts/*"
- Exclua também todos os resultados cujo caminho comece com ./scripts/
Testando a solução:
$ mkdir a b c d e
$ touch a/1 b/2 c/3 d/4 e/5 e/a e/b
$ find . -type f ! -path "./a/*" ! -path "./b/*"
./d/4
./c/3
./e/a
./e/b
./e/5
Você chegou bem perto, a -name
opção considera apenas o nome de base, onde as -path
considera todo o caminho =)
_peaks.bed
.find
, mas como a questão está marcada como Linux, isso não é um problema. Boa resposta..
em seu prompt de localização inicial, terá que usá-lo em cada caminho que excluir. A correspondência de caminho é bastante restrita, não faz pesquisas difusas. Então, se você usar,find / -type f -name *.bed" ! -path "./tmp/"
não vai funcionar. você precisa ter! -path "/tmp"
que torná-lo feliz.$ ! -path "./directory/*"
-prune
vez de verificar todos os arquivos na árvore." Se os diretórios excluídos forem muito profundos ou tiverem toneladas de arquivos e você se preocupa com o desempenho, use a-prune
opção.Aqui está uma maneira de fazer isso ...
find . -type f -name "*_peaks.bed" | egrep -v "^(./tmp/|./scripts/)"
fonte
find
, em vez de apenas com o GNUfind
. No entanto, a questão é marcada Linux para que não seja crítica.Usar
find \( -path "./tmp" -o -path "./scripts" \) -prune -o -name "*_peaks.bed" -print
ou
find \( -path "./tmp" -o -path "./scripts" \) -prune -false -o -name "*_peaks.bed"
ou
find \( -path "./tmp" -path "./scripts" \) ! -prune -o -name "*_peaks.bed"
A ordem é importante. Ele avalia da esquerda para a direita. Sempre comece com a exclusão do caminho.
Explicação
Não use
-not
(ou!
) para excluir o diretório inteiro. Use-prune
. Conforme explicado no manual:e no manual de localização do GNU:
Na verdade, se você usar
-not -path "./pathname"
, find avaliará a expressão para cada nó em"./pathname"
.encontrar expressões são apenas avaliações de condições.
\( \)
- operação de grupos (você pode usar-path "./tmp" -prune -o -path "./scripts" -prune -o
, mas é mais detalhado).-path "./script" -prune
- se-path
retorna verdadeiro e é um diretório, retorna verdadeiro para aquele diretório e não desce para ele.-path "./script" ! -prune
- avalia como(-path "./script") AND (! -prune)
. Ele reverte o "sempre verdadeiro" da poda para sempre falso. Isso evita a impressão"./script"
como um fósforo.-path "./script" -prune -false
- como-prune
sempre retorna true, você pode seguir com-false
para fazer o mesmo que!
.-o
- Operador OR. Se nenhum operador for especificado entre duas expressões, o padrão é o operador AND.Portanto,
\( -path "./tmp" -o -path "./scripts" \) -prune -o -name "*_peaks.bed" -print
é expandido para:[ (-path "./tmp" OR -path "./script") AND -prune ] OR ( -name "*_peaks.bed" AND print )
A impressão é importante aqui porque sem ela é expandida para:
{ [ (-path "./tmp" OR -path "./script" ) AND -prune ] OR (-name "*_peaks.bed" ) } AND print
-print
é adicionado por find - é por isso que na maioria das vezes, você não precisa adicioná-lo em sua expressão. E como-prune
retorna true, ele irá imprimir "./script" e "./tmp".Não é necessário nas outras porque mudamos
-prune
para sempre retornar falso.Dica: você pode usar
find -D opt expr 2>&1 1>/dev/null
para ver como está otimizado e expandido,find -D search expr 2>&1 1>/dev/null
para ver qual caminho está marcado.fonte
Tente algo como
find . \( -type f -name \*_peaks.bed -print \) -or \( -type d -and \( -name tmp -or -name scripts \) -and -prune \)
e não se surpreenda se eu errar um pouco. Se o objetivo for um exec (em vez de impressão), basta substituí-lo no lugar.
fonte
para mim, esta solução não funcionou em um exec de comando com find, realmente não sei por que, então minha solução é
find . -type f -path "./a/*" -prune -o -path "./b/*" -prune -o -exec gzip -f -v {} \;
Explicação: o mesmo que sampson-chen um com a adição de
-prune - ignora o caminho de procedimento de ...
-o - Então, se não houver correspondência, imprime os resultados (remova os diretórios e imprima os resultados restantes)
18:12 $ mkdir a b c d e 18:13 $ touch a/1 b/2 c/3 d/4 e/5 e/a e/b 18:13 $ find . -type f -path "./a/*" -prune -o -path "./b/*" -prune -o -exec gzip -f -v {} \; gzip: . is a directory -- ignored gzip: ./a is a directory -- ignored gzip: ./b is a directory -- ignored gzip: ./c is a directory -- ignored ./c/3: 0.0% -- replaced with ./c/3.gz gzip: ./d is a directory -- ignored ./d/4: 0.0% -- replaced with ./d/4.gz gzip: ./e is a directory -- ignored ./e/5: 0.0% -- replaced with ./e/5.gz ./e/a: 0.0% -- replaced with ./e/a.gz ./e/b: 0.0% -- replaced with ./e/b.gz
fonte
find . -path ./scripts -prune -name '*_peaks.bed' -type f
,. Não tenho certeza de como excluir vários diretórios. Isso também lista o diretório excluído de nível superior, emboratype
seja especificado. Excluir via Grep parece mais simples, a menos que você queira usar poda para acelerar a operação de localização.Você pode tentar abaixo:
find ./ ! \( -path ./tmp -prune \) ! \( -path ./scripts -prune \) -type f -name '*_peaks.bed'
fonte