find . -type f -name '*f*' | sed -r 's|/[^/]+$||' |sort |uniq
Lo anterior encuentra todos los archivos debajo del directorio actual ( .
) que son archivos normales ( -type f
) y tienen f
algún lugar en su nombre ( -name '*f*'
). A continuación, sed
elimina el nombre del archivo, dejando solo el nombre del directorio. Luego, la lista de directorios se ordena ( sort
) y se eliminan los duplicados ( uniq
).
El sed
comando consiste en un solo sustituto. Busca coincidencias con la expresión regular /[^/]+$
y reemplaza todo lo que coincida con nada. El signo de dólar significa el final de la línea. [^/]+'
significa uno o más caracteres que no son barras. Por lo tanto, /[^/]+$
significa todos los caracteres desde la barra final hasta el final de la línea. En otras palabras, esto coincide con el nombre del archivo al final de la ruta completa. Por lo tanto, el comando sed elimina el nombre del archivo, dejando sin cambios el nombre del directorio en el que estaba el archivo.
Simplificaciones
Muchos sort
comandos modernos admiten una -u
bandera que hace uniq
innecesaria. Para GNU sed:
find . -type f -name '*f*' | sed -r 's|/[^/]+$||' |sort -u
Y, para MacOS sed:
find . -type f -name '*f*' | sed -E 's|/[^/]+$||' |sort -u
Además, si su find
comando lo admite, es posible find
imprimir directamente los nombres de directorio. Esto evita la necesidad de sed
:
find . -type f -name '*f*' -printf '%h\n' | sort -u
Versión más robusta (requiere herramientas GNU)
Las versiones anteriores se confundirán con los nombres de archivo que incluyen nuevas líneas. Una solución más robusta es hacer la clasificación en cadenas terminadas en NUL:
find . -type f -name '*f*' -printf '%h\0' | sort -zu | sed -z 's/$/\n/'
uniq
en la mezcla ayuda mucho al eliminar las líneas repetidas que ya están una al lado de la otra.find . -type f -name '*f*' -printf '%h\0' | uniq -z | sort -zu | tr '\0' '\n'
. O si sus herramientas son un poco más antiguas, entonces uniq puede no tener la opción -z.find . -type f -name '*f*' -printf '%h\n' | uniq | sort -u
-E
para MacOS.¿Por qué no probar esto?
fuente
find
son bastante escasas: el-printf
operador no está especificado. Esto no funciona con BSDfind
. Por lo tanto, no es "totalmente compatible con POSIX". (Aunquesort -u
está en POSIX .)Básicamente, existen 2 métodos que puede usar para hacer esto. Uno analizará la cadena mientras que el otro operará en cada archivo. El análisis de la cadena usa una herramienta como
grep
,sed
oawk
obviamente será más rápido, pero aquí hay un ejemplo que muestra ambos, así como también cómo puedes "perfilar" los 2 métodos.Data de muestra
Para los ejemplos a continuación usaremos los siguientes datos
Eliminar algunos de los
*f*
archivos dedir1/*
:Enfoque n. ° 1: análisis a través de cadenas
Aquí vamos a utilizar las siguientes herramientas,
find
,grep
, ysort
.Enfoque n. ° 2: análisis mediante archivos
La misma cadena de herramientas que antes, excepto que esta vez usaremos en
dirname
lugar degrep
.NOTA: Los ejemplos anteriores se utilizan
head -5
para limitar simplemente la cantidad de salida que estamos tratando para estos ejemplos. ¡Normalmente se eliminarían para obtener su listado completo!Comparando los resultados
Podemos usar
time
para echar un vistazo a los 2 enfoques.dirname
grep
Por lo tanto, siempre es mejor lidiar con las cadenas si es posible.
Métodos alternativos de análisis de cadenas
grep y PCRE
sed
awk
fuente
Aquí hay uno que me parece útil:
fuente
Esta respuesta se basa descaradamente en la respuesta slm. Fue un enfoque interesante, pero tiene una limitación si los nombres de archivo y / o directorio tienen caracteres especiales (espacio, semicolumna ...). Un buen hábito es usar
find /somewhere -print0 | xargs -0 someprogam
.Data de muestra
Para los ejemplos a continuación usaremos los siguientes datos
Eliminar algunos de los
*f*
archivos dedir1/*/
:Enfoque n. ° 1: análisis mediante archivos
NOTA : Los ejemplos anteriores se utilizan
head -5
para limitar simplemente la cantidad de salida que estamos tratando para estos ejemplos. ¡Normalmente se eliminarían para obtener su listado completo! Además, reemplace elecho
comando que quiera usar.fuente
Con
zsh
:fuente