Por que encontrar -exec du sum de maneira diferente?

4

Tenho fotos e filmes de família em uma pasta / mídia / dados / Selbstgemacht e gostaria de encontrar o tamanho de todas as fotos. Em / media / data eu uso find Selbstgemacht -type f -iname '*.jpg' -exec du -ch '{}' + , que retorna 5,1 GB.
No entanto, se eu descer para a pasta "Selbstgemacht" e usar find . -type f -iname '*.jpg' -exec du -ch '{}' + , ele retornará 7,0 GB.

Eu então comparei a saída do find para verificar se eles encontraram os mesmos arquivos:
Da pasta pai find Selbstgemacht -type f -iname '*.jpg' -printf '%P\n' |sort > test1.txt
De subpasta find . -type f -iname '*.jpg' -printf '%P\n' |sort > ../test2.txt

Os arquivos são idênticos, então ambos os comandos find encontram exatamente os mesmos arquivos, o que me leva a pensar que a diferença no tamanho dos relatórios deve ser devido a outra coisa.

Qual é exatamente a causa aqui?

Informação do sistema:

  • estável do Debian
  • find (GNU findutils) 4.4.2
    • D_TYPE O_NOFOLLOW (ativado)
    • LEAF_OPTIMISATION, FTS (), CBO (nível = 0)
  • du (GNU coreutils) 8.13
por Jan 05.08.2014 / 10:33

2 respostas

6

find ... -exec cmd {} + executará cmd quantas vezes forem necessárias para não quebrar o limite do tamanho dos argumentos passados para um comando.

Ao usar find . -exec du {} + , o tamanho da lista de arquivos é menor do que ao usar find verylongdirname -exec du {} + .

Portanto, é provável que find verylongdirname execute mais comandos du do que find . one. O total que você vê no final é o total da última execução em du , que não inclui todos os arquivos (já houve mais totais anteriores, você pode canalizar o comando para grep 'total$' para confirmar.

    
por 05.08.2014 / 10:44
2

O que você deve ver é que, em ambos os casos, você provavelmente não obterá o uso de espaço em disco de suas imagens. Se você tem milhares de fotos, provavelmente em ambos os casos excede o limite para a chamada exec.

Por quê? Bem, o comando -exec (...) + adiciona parâmetros à chamada do sistema execvp . A página man define o limite de sua chamada de sistema subjacente como segue (extrair da página de manual execve ):

Limits on size of arguments and environment
   Most UNIX implementations impose some limit on the total  size  of  the
   command-line argument (argv) and environment (envp) strings that may be
   passed to a new program. (...)

   On  kernel  2.6.23  and  later, most architectures support a size limit
   derived from the soft RLIMIT_STACK resource  limit  (see  getrlimit(2))
   that is in force at the time of the execve() call.  (...)   This change
   allows programs to have a much larger argument and/or environment list.
   For these  architectures,  the  total  size  is  limited  to 1/4 of the
   allowed stack size. (...) Since Linux 2.6.25, the kernel places a floor
   of 32 pages on this size limit, so that, even when RLIMIT_STACK is  set
   very low, applications are guaranteed to have at least as much argument
   and environment space as was provided by Linux 2.6.23 and earlier (This
   guarantee  was not provided in Linux 2.6.23 and 2.6.24.)  Additionally,
   the limit per string is 32 pages (the kernel constant  MAX_ARG_STRLEN),
   and the maximum number of strings is 0x7FFFFFFF.

Portanto, se você tiver uma longa lista de arquivos, poderá atingir rapidamente os limites do sistema. Além disso, quando o caminho relativo é maior, ele está usando mais memória, o que pode fazer com que você atinja os limites mais rapidamente, daí os resultados diferentes de seus dois comandos.

Existe uma solução

Uma solução nos sistemas GNU é usar uma lista de entrada de arquivos para du usando as opções --files0-from . Com o seu exemplo:

find Selbstgemacht -type f -iname '*.jpg' -print0 | du --files0-from=- -ch

O primeiro comando lista todos os arquivos e os gera na saída padrão separada por NUL ( du ). Essa lista é "ingerida" por - da entrada padrão (o du nome do arquivo) e %code% soma o total.

    
por 06.08.2014 / 13:16