Respuestas:
Aquí hay un enfoque completamente diferente basado en GNU find
y uniq
. Esto es mucho más rápido y amigable con la CPU que las respuestas basadas en la ejecución de un comando de shell que cuenta archivos para cada directorio encontrado.
find . -type f -printf '%h\n' | sort | uniq -d
El find
comando imprime el directorio de todos los archivos en la jerarquía y uniq
solo muestra los directorios que aparecen al menos dos veces.
-printf '%h\0' | sort -z | uniq -zd | xargs -r0 ...
find . -type d \
-exec sh -c 'c=0; for n in "$1"/*; do [ -f "$n" ] && [ ! -h "$n" ] && c=$(( c + 1 )); done; [ "$c" -ge 2 ]' sh {} ';' \
-print
Esto encontrará todos los nombres dentro o debajo del directorio actual y luego filtrará todos los nombres que no sean nombres de directorios.
Los nombres de directorio restantes se darán a este breve script:
c=0
for n in "$1"/*; do
[ -f "$n" ] && [ ! -h "$n" ] && c=$(( c + 1 ))
done
[ "$c" -ge 2 ]
Este script contará el número de archivos regulares (omitiendo enlaces simbólicos) en el directorio dado como el primer argumento de línea de comando (desde find
). El último comando en el script es una prueba para ver si el recuento fue 2 o mayor. El resultado de esta prueba es el valor de retorno (estado de salida) del script.
Si la prueba tuvo éxito, -print
hará find
que se imprima la ruta al directorio.
Para considerar también los archivos ocultos (archivos cuyos nombres comienzan con un punto), cambie la sh -c
secuencia de comandos de decir
for n in "$1"/*; do
a
for n in "$1"/* "$1"/.*; do
Pruebas:
$ tree
.
`-- test
|-- a
|-- dir1
| |-- a
| |-- b
| `-- c
`-- dir2
|-- dira
|-- dirb
| |-- file-1
| `-- file-2
`-- dirc
6 directories, 6 files
$ find . -type d -exec sh -c 'c=0; for n in "$1"/*; do [ -f "$n" ] && [ ! -h "$n" ] && c=$(( c + 1 )); done; [ "$c" -ge 2 ]' sh {} ';' -print
./test/dir1
./test/dir2/dirb
[ "" -ge 2 ]
es una prueba válida.
dash
, bash --posix
y test
todos muestran un mensaje de error y salen con 2 (es decir, "Se produjo un error")
ksh
funcionaba como sh
. Se enmendará de inmediato. ¡Gracias por molestarme! :-)
[ -f ... ]
referencia a enlaces simbólicos. Debe agregar una prueba para eliminarlos, ya que la pregunta especifica que solo se deben contar los archivos normales.
Con la ayuda de la respuesta de Gilles sobre SU y su reversa y algunas modificaciones, aquí está lo que necesita.
find . -type d -exec sh -c 'set -- "$1"/*;X=0;
for args; do [ -f "$args" ] && X=$((X+1)) ;done; [ "$X" -gt 1 ] ' _ {} \; -print
Árbol de directorios.
.
├── test
│ ├── dir1
│ │ ├── a
│ │ ├── b
│ │ └── c
│ ├── dir2
│ │ ├── dira
│ │ │ └── a file\012with\012multiple\012line
│ │ ├── dirb
│ │ │ ├── file-1
│ │ │ └── file-2
│ │ └── dirc
│ ├── diraa
│ ├── dirbb
│ ├── dircc
│ └── x
│ └── x1
│ └── x2
└── test2
├── dir3
└── dir4
Resultado:
./test
./test/dir1
./test/dir2/dirb
test
los dir2
directorios y en mi configuración de prueba (ver mi respuesta).
test/x1
y test/x2
como archivos también ... $1
y $2
serán directorios para test
, y se perderá el directorio.
Otro enfoque find
+ wc
:
find path/currdir -maxdepth 1 -type d ! -empty ! -path "path/currdir" \
-exec sh -c 'count=$(find "$1" -maxdepth 1 -type f | wc -l); [ $count -ge 2 ]' _ {} \; -print
path/currdir
- ruta a su directorio actual
-maxdepth 1
- considere solo subcarpetas secundarias directas
! -empty
- ignorar subcarpetas vacías
! -path "path/currdir"
- ignorar la ruta actual del directorio
count=$(find "$1" -maxdepth 1 -type f | wc -l)
- count
se le asigna el número de archivos para cada subcarpeta encontrada
[ $count -ge 2 ] ... -print
- imprimir nombre / ruta de subcarpeta que contiene 2 o más archivos regulares
find
. En este caso, porque GNUfind
destrozará los nombres de directorios que tienen caracteres que no se pueden imprimir en la configuración regional actual (como "ä" en la configuración regional en C). Consulte también unix.stackexchange.com/questions/321697/…