Nome do primeiro arquivo no diretório obtido de maneira ótima

1

Ordinário quando eu quero mostrar o nome do primeiro arquivo do diretório que eu digito:

ls raw/all | head -n 1

Mas leva muito tempo quando no diretório existem muitos arquivos

Por exemplo, para arquivos dir próximos a 900 k, temos as seguintes medidas:

time ls raw/all | head -n 1 

real    0m17.250s | 0m10.328s | 0m6.334s
user    0m3.224s  | 0m3.884s  | 0m3.192s
sys     0m0.544s  | 0m0.664s  | 0m0.572s

enquanto o loop sobre todos os arquivos leva:

time ls raw/all | wc -l

real    0m6.455s | 0m5.869s  | 0m5.228s
user    0m3.612s | 0m3.468s  | 0m4.072s
sys     0m0.460s | 0m0.784s  | 0m0.624s

Como imprime o nome do primeiro arquivo na maneira eficiente ?

    
por Daniel 16.08.2017 / 16:51

1 resposta

2

Isso é complicado. Duas abordagens:

Abordagem 1; find :

find . -mindepth 1 -print -quit

find e -print s o primeiro arquivo encontrado e -quit s imediatamente. -mindepth 1 impediria a correspondência do hardlink . do diretório atual.

Se você estiver interessado apenas em arquivos regulares, adicione -type f :

find . -type f  -print -quit

-mindepth 1 pode ser descartado, pois o . sendo um diretório não seria correspondido.

Abordagem 2; sh , stdbuf e awk :

Note que, isso pode sofrer ARG_MAX sendo acionado para muitos arquivos (a lista de argumentos está se tornando muito longa, acima de ARG_MAX bytes). Nesse caso, use a abordagem 1.

  • qualquer shell builin (por exemplo, printf , echo ) para imprimir o nome do arquivo
  • shell globbing, * , para fazer a expansão (a ordem de agrupamento deve ser igual a ls para um dado locale ' LC_COLLATE )
  • stdbuf -o0 ( stdbuf vem com GNU coreutils ) para tornar o fluxo STDOUT de printf / echo unbuffered
  • pipe ( | ) o STDOUT de printf / echo a awk e exit depois de imprimir o primeiro registro
  • Após awk sair, stdbuf ( printf ) receberia SIGPIPE e seria eliminado
  • Eu usaria printf para obter os nomes de arquivos separados por ASCII NUL ( awk ) e use %code% como o separador de registro em %code% para lidar com casos de borda no que diz respeito aos nomes de arquivos

Colocando estes juntos:

stdbuf -o0 printf '%s
find . -mindepth 1 -print -quit
' * | awk 'BEGIN{RS="
find . -type f  -print -quit
"} {print; exit}'
    
por heemayl 16.08.2017 / 17:06