A abordagem de @ meuh é ineficiente, pois -maxdepth 1
ainda permite find
ler o conteúdo dos diretórios no nível 1 para depois ignorá-los. Também não funcionará corretamente com algumas find
implementações (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 GNU -maxdepth 1
(ou FreeBSD -depth -2
).
Geralmente, porém, é o que -depth 1
você deseja ( -mindepth 1 -maxdepth 1
), como não deseja considerar .
(profundidade 0), e é ainda mais simples:
find . ! -name . -prune -extra-conditions-and-actions
Pois -maxdepth 2
, isso se torna:
find . \( ! -path './*/*' -o -prune \) -extra-conditions-and-actions
E é aí que você executa os problemas de caracteres inválidos.
Por exemplo, se você tiver um diretório chamado, Stéphane
mas é
codificado no charset iso8859-1 (também conhecido como latin1) (0xe9 byte), como era mais comum na Europa Ocidental e na América até meados da década de 2000, esse byte 0xe9 não é um caractere válido em UTF-8. Portanto, nos códigos de idioma UTF-8, o *
curinga (com algumas find
implementações) não corresponderá Stéphane
com *
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 era 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 find
e qualquer aplicativo executado (como por meio dos -exec
predicados).
$ LC_ALL=C find . \( ! -path './*/*' -o -prune \)
.
./St?phane
./St?phane/Chazelas
./St??phane
./St??phane/Chazelas
./John
./John/Smith
Agora, eu realmente entendo -maxdepth 2
como o é no segundo Stéphane corretamente codificado em UTF-8 é exibido ??
como os bytes 0xc3 0xa9 (considerados como dois caracteres indefinidos individuais no código de idioma C) da codificação UTF-8 de é caracteres imprimíveis no código de idioma C.
E se eu tivesse adicionado um -name '????????'
, eu teria pegado o Stéphane errado (aquele codificado em iso8859-1).
Para aplicar a caminhos arbitrários em vez de .
, faça:
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 ocorram em problemas de caminho muito longo ou a lista de argumentos muito longa , mas também para contornar o fato de que find
não é possível suportar argumentos arbitrários de caminho (exceto -f
com o FreeBSD find
), pois ele se engasga com valores de $dir
like !
ou -print
...
A -o
combinação com negação é um truque comum para executar dois conjuntos independentes de -condition
/ -action
in find
.
Se você deseja executar -action1
em reunião de arquivos -condition1
e independentemente -action2
em reunião de arquivos -condition2
, não é possível:
find . -condition1 -action1 -condition2 -action2
Como -action2
seria executado apenas para arquivos que atendam às duas condições.
Nem:
find . -contition1 -action1 -o -condition2 -action2
Como -action2
não seria executado para arquivos que atendam às duas condições.
find . \( ! -condition1 -o -action1 \) -condition2 -action2
funciona como se \( ! -condition1 -o -action1 \)
fosse verdadeiro para todos os arquivos. Isso pressupõe que -action1
é uma ação (como -prune
, -exec ... {} +
) que sempre retorna verdadeira . Para ações como -exec ... \;
essa, pode retornar falso , você pode adicionar outro -o -something
onde -something
é inofensivo, mas retorna verdadeiro como -true
no GNU find
ou -links +0
ou -name '*'
(embora observe o problema sobre caracteres inválidos acima).
-depth -2
,-depth 1
... poderia ser vista como melhor que a do GNU-maxdepth
/ /-mindepth