Aquí hay una forma en que podrías hacerlo...
find . -type f -name "*_peaks.bed" | egrep -v "^(./tmp/|./scripts/)"
para mí, esta solución no funcionó en un comando ejecutivo con find, realmente no sé por qué, así que mi solución es
find . -type f -path "./a/*" -prune -o -path "./b/*" -prune -o -exec gzip -f -v {} \;
Explicación: igual que sampson-chen uno con las adiciones de
-prune - ignora la ruta anterior de ...
-o - Luego, si no hay coincidencias, imprime los resultados (elimina los directorios e imprime los 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
Así es como puede especificar eso con find
:
find . -type f -name "*_peaks.bed" ! -path "./tmp/*" ! -path "./scripts/*"
Explicación:
find .
- Iniciar búsqueda desde el directorio de trabajo actual (recursivamente por defecto)-type f
- Especificar afind
que solo quieres archivos en los resultados-name "*_peaks.bed"
- Busque archivos cuyo nombre termine en_peaks.bed
! -path "./tmp/*"
- Excluir todos los resultados cuya ruta comience con./tmp/
! -path "./scripts/*"
- También excluya todos los resultados cuya ruta comience con./scripts/
Probar la solución:
$ 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
Estuviste bastante cerca, el -name
La opción solo considera el nombre base, mientras que -path
considera todo el camino =)
Usar
find \( -path "./tmp" -o -path "./scripts" \) -prune -o -name "*_peaks.bed" -print
o
find \( -path "./tmp" -o -path "./scripts" \) -prune -false -o -name "*_peaks.bed"
o
find \( -path "./tmp" -path "./scripts" \) ! -prune -o -name "*_peaks.bed"
El orden es importante. Se evalúa de izquierda a derecha. Siempre comience con la exclusión de la ruta.
Explicación
No use -not
(o !
) para excluir todo el directorio. Utilice -prune
.Como se explica en el manual:
−prune The primary shall always evaluate as true; it
shall cause find not to descend the current
pathname if it is a directory. If the −depth
primary is specified, the −prune primary shall
have no effect.
y en el manual de búsqueda de GNU:
-path pattern
[...]
To ignore a whole
directory tree, use -prune rather than checking
every file in the tree.
De hecho, si usa -not -path "./pathname"
,find evaluará la expresión para cada nodo bajo "./pathname"
.
Las expresiones de búsqueda son solo evaluación de condiciones.
\( \)
- operación de grupos (puede usar-path "./tmp" -prune -o -path "./scripts" -prune -o
, pero es más detallado).-path "./script" -prune
- si-path
devuelve verdadero y es un directorio, devuelve verdadero para ese directorio y no descender a él.-path "./script" ! -prune
- se evalúa como(-path "./script") AND (! -prune)
. Revierte el "siempre verdadero" de ciruela pasa a siempre falso. Evita imprimir"./script"
como un partido.-path "./script" -prune -false
- desde-prune
siempre devuelve verdadero, puedes seguirlo con-false
hacer lo mismo que!
.-o
- Operador O. Si no se especifica ningún operador entre dos expresiones, el valor predeterminado es el operador AND.
Por lo tanto, \( -path "./tmp" -o -path "./scripts" \) -prune -o -name "*_peaks.bed" -print
se expande a:
[ (-path "./tmp" OR -path "./script") AND -prune ] OR ( -name "*_peaks.bed" AND print )
La impresión es importante aquí porque sin ella se expande a:
{ [ (-path "./tmp" OR -path "./script" ) AND -prune ] OR (-name "*_peaks.bed" ) } AND print
-print
se agrega mediante find; es por eso que la mayoría de las veces, no necesita agregarlo en su expresión. Y desde -prune
devuelve verdadero, imprimirá "./script" y "./tmp".
En los demás no es necesario porque cambiamos -prune
para devolver siempre falso.
Pista:puedes usar find -D opt expr 2>&1 1>/dev/null
para ver cómo se optimiza y amplía,
find -D search expr 2>&1 1>/dev/null
para ver qué ruta está marcada.