El enfoque de @meuh es ineficiente ya que su -maxdepth 1
enfoque todavía permite find
leer el contenido de los directorios en el nivel 1 para luego ignorarlos de lo contrario. Tampoco funcionará correctamente con algunas find
implementaciones (incluida GNU find
) si algunos nombres de directorio contienen secuencias de bytes que no forman caracteres válidos en la configuración regional del usuario (como para los nombres de archivo en una codificación de caracteres diferente).
find . \( -name . -o -prune \) -extra-conditions-and-actions
es la forma más canónica de implementar GNU -maxdepth 1
(o FreeBSD -depth -2
).
En general, es lo -depth 1
que quieres ( -mindepth 1 -maxdepth 1
), ya que no quieres considerarlo .
(profundidad 0), y luego es aún más simple:
find . ! -name . -prune -extra-conditions-and-actions
Porque -maxdepth 2
eso se convierte en:
find . \( ! -path './*/*' -o -prune \) -extra-conditions-and-actions
Y ahí es donde se ejecutan los problemas de caracteres no válidos.
Por ejemplo, si tiene un directorio llamado Stéphane
pero que é
está codificado en el conjunto de caracteres iso8859-1 (también conocido como latin1) (0xe9 byte) como era más común en Europa occidental y América hasta mediados de la década de 2000, entonces ese byte 0xe9 no es un Carácter válido en UTF-8. Por lo tanto, en las configuraciones regionales UTF-8, el *
comodín (con algunas find
implementaciones) no coincidirá, Stéphane
ya que *
es 0 o más caracteres y 0xe9 no es un carácter.
$ locale charmap
UTF-8
$ find . -maxdepth 2
.
./St?phane
./St?phane/Chazelas
./Stéphane
./Stéphane/Chazelas
./John
./John/Smith
$ find . \( ! -path './*/*' -o -prune \)
.
./St?phane
./St?phane/Chazelas
./St?phane/Chazelas/age
./St?phane/Chazelas/gender
./St?phane/Chazelas/address
./Stéphane
./Stéphane/Chazelas
./John
./John/Smith
Mi find
(cuando la salida va a una terminal) muestra ese byte 0xe9 inválido como el ?
anterior. Puedes ver que St<0xe9>phane/Chazelas
no fue prune
d.
Puede solucionarlo haciendo:
LC_ALL=C find . \( ! -path './*/*' -o -prune \) -extra-conditions-and-actions
Pero tenga en cuenta que eso afecta a toda la configuración regional find
y a cualquier aplicación que ejecute (como a través de los -exec
predicados).
$ LC_ALL=C find . \( ! -path './*/*' -o -prune \)
.
./St?phane
./St?phane/Chazelas
./St??phane
./St??phane/Chazelas
./John
./John/Smith
Ahora, realmente obtengo un mensaje, -maxdepth 2
pero tenga en cuenta cómo el é en el segundo Stéphane codificado correctamente en UTF-8 se muestra ??
como los 0xc3 0xa9 bytes (considerados como dos caracteres indefinidos individuales en el entorno C) de la codificación UTF-8 de é caracteres no imprimibles en la configuración regional C.
Y si hubiera agregado un -name '????????'
, habría obtenido el Stéphane incorrecto (el codificado en iso8859-1).
Para aplicar a rutas arbitrarias en lugar de hacerlo .
, haría lo siguiente:
find some/dir/. ! -name . -prune ...
para -mindepth 1 -maxdepth 1
o:
find some/dir/. \( ! -path '*/./*/*' -o -prune \) ...
para -maxdepth 2
.
Todavía haría un:
(cd -P -- "$dir" && find . ...)
Primero porque eso hace que las rutas sean más cortas, lo que hace que sea menos probable que se encuentre con una ruta demasiado larga o que contengafind
argumentos demasiado largos , pero también que evite el hecho de que no puede admitir argumentos de ruta arbitraria (excepto -f
con FreeBSD find
) ya que se ahogará valores de me $dir
gusta !
o -print
...
En -o
combinación con la negación es un truco común para ejecutar dos conjuntos independientes de -condition
/ -action
in find
.
Si desea ejecutar -action1
en reunión de archivos -condition1
e independientemente -action2
en reunión de archivos -condition2
, no puede hacer:
find . -condition1 -action1 -condition2 -action2
Como -action2
solo se ejecutaría para archivos que cumplan ambas condiciones.
Ni:
find . -contition1 -action1 -o -condition2 -action2
Como -action2
no se ejecutaría para archivos que cumplan ambas condiciones.
find . \( ! -condition1 -o -action1 \) -condition2 -action2
funciona como \( ! -condition1 -o -action1 \)
se resolvería a verdadero para cada archivo. Eso supone que -action1
es una acción (como -prune
, -exec ... {} +
) que siempre devuelve verdadero . Por acciones como -exec ... \;
que pueden volver falsa , es posible que desee agregar otro -o -something
donde -something
es inofensivo pero devuelve cierto como -true
en GNU find
o -links +0
o -name '*'
(aunque tenga en cuenta la cuestión acerca de caracteres no válidos anteriores).
-depth -2
,-depth 1
... el enfoque podría ser visto como mejor que el de GNU-maxdepth
/-mindepth