A abordagem do meuh é ineficiente, pois sua abordagem -maxdepth 1
ainda permite que find
leia o conteúdo dos diretórios no nível 1 para depois ignorá-los. Ele também não funcionará corretamente com algumas implementações de find
(incluindo GNU find
) se alguns nomes de diretório contiverem seqüências de bytes que não formam caracteres válidos no código do idioma do usuário (como para nomes de arquivos em uma codificação de caracteres diferente).
find . \( -name . -o -prune \) -extra-conditions-and-actions
é a maneira mais canônica de implementar o -maxdepth 1
do GNU (ou -depth -2
do FreeBSD).
Geralmente, é -depth 1
que você quer ( -mindepth 1 -maxdepth 1
) porque você não quer considerar .
(profundidade 0), e então é ainda mais simples:
find . ! -name . -prune -extra-conditions-and-actions
Para -maxdepth 2
, isso se torna:
find . \( ! -path './*/*' -o -prune \) -extra-conditions-and-actions
E é aí que você executa os problemas de caractere inválido.
Por exemplo, se você tiver um diretório chamado Stéphane
, mas que é
esteja codificado no conjunto de caracteres iso8859-1 (também conhecido como latin1) (0xe9 byte), como era mais comum na Europa Ocidental e na América até meados 2000s, então esse 0xe9 byte não é um caractere válido em UTF-8. Portanto, nas localidades UTF-8, o curinga *
(com algumas find
implementações) não corresponderá a Stéphane
, pois *
é 0 ou mais caracteres e 0xe9 não é um caractere.
$ 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
Meu find
(quando a saída vai para um terminal) exibe esse byte 0xe9 inválido como ?
acima. Você pode ver que St<0xe9>phane/Chazelas
não foi prune
d.
Você pode contornar isso fazendo:
LC_ALL=C find . \( ! -path './*/*' -o -prune \) -extra-conditions-and-actions
Mas observe que isso afeta todas as configurações de localidade de find
e qualquer aplicativo executado (como os predicados -exec
).
$ LC_ALL=C find . \( ! -path './*/*' -o -prune \)
.
./St?phane
./St?phane/Chazelas
./St??phane
./St??phane/Chazelas
./John
./John/Smith
Agora, eu realmente obtenho um -maxdepth 2
, mas observe como o é no segundo Stéphane corretamente codificado em UTF-8 é exibido como ??
como os bytes 0xc3 0xa9 (considerados como dois caracteres indefinidos individuais no idioma C) da codificação UTF-8 de é não são caracteres imprimíveis na localidade C.
E se eu tivesse adicionado um -name '????????'
, eu teria recebido o Stéphane errado (o codificado em iso8859-1).
Para aplicar a caminhos arbitrários em vez de .
, você faria:
find some/dir/. ! -name . -prune ...
para -mindepth 1 -maxdepth 1
ou:
find some/dir/. \( ! -path '*/./*/*' -o -prune \) ...
para -maxdepth 2
.
Eu ainda faria um:
(cd -P -- "$dir" && find . ...)
Primeiro, porque isso torna os caminhos mais curtos, o que torna menos provável que aconteça em caminho muito longo ou lista de args por muito tempo , mas também para contornar o fato de que find
não suporta argumentos de caminho arbitrário (exceto com -f
com FreeBSD find
), já que ele irá bloquear os valores de $dir
como !
ou -print
...
O -o
em combinação com a negação é um truque comum para executar dois conjuntos independentes de -condition
/ -action
em find
.
Se você deseja executar -action1
nos arquivos que atendem -condition1
e independentemente -action2
nos arquivos que atendem -condition2
, não é possível fazer isso:
find . -condition1 -action1 -condition2 -action2
Como -action2
seria executado apenas para arquivos que atendem às condições ambos .
Nor:
find . -contition1 -action1 -o -condition2 -action2
Como -action2
não seria executado para arquivos que atendem às condições ambas .
find . \( ! -condition1 -o -action1 \) -condition2 -action2
funciona como \( ! -condition1 -o -action1 \)
resolveria para true para cada arquivo. Isso pressupõe que -action1
é uma ação (como -prune
, -exec ... {} +
) que sempre retorna true . Para ações como -exec ... \;
que podem retornar false , você pode adicionar outro -o -something
onde -something
é inofensivo, mas retorna verdadeiro como -true
no GNU find
ou -links +0
ou -name '*'
(no entanto, observe o problema sobre caracteres inválidos acima).