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 falgún lugar en su nombre ( -name '*f*'). A continuación, sedelimina 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 sedcomando 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 sortcomandos modernos admiten una -ubandera que hace uniqinnecesaria. 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 findcomando lo admite, es posible findimprimir 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/'
uniqen 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-Epara MacOS.¿Por qué no probar esto?
fuente
findson bastante escasas: el-printfoperador no está especificado. Esto no funciona con BSDfind. Por lo tanto, no es "totalmente compatible con POSIX". (Aunquesort -uestá 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,sedoawkobviamente 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
dirnamelugar degrep.NOTA: Los ejemplos anteriores se utilizan
head -5para 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
timepara 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 -5para limitar simplemente la cantidad de salida que estamos tratando para estos ejemplos. ¡Normalmente se eliminarían para obtener su listado completo! Además, reemplace elechocomando que quiera usar.fuente
Con
zsh:fuente