Como o script de shell a seguir funciona na localização de todos os arquivos maiores que 20MB?

0

Me deparei com um post informando que o seguinte encontrará todos os arquivos com mais de 20 MB.

find / -type f -size +20000k -exec ls -lh {} \; 2> /dev/null   | awk '{ print $NF ": " $5 }'  | sort -hrk 2,2

Parece funcionar, mas tentando entender o que está acontecendo depois que o '+ 20000k' está causando um curto-circuito no meu cérebro. Alguém pode por favor quebrar para mim?

    
por Stuart Law 29.09.2014 / 13:43

4 respostas

6

find / -type f -size +20000k -exec ls -lh {} \; 2> /dev/null   | awk '{ print $NF ": " $5 }'  | sort -hrk 2,2
  • / : find começa no diretório principal
  • -type f : encontre apenas arquivos regulares
  • -size +20000k : com tamanho 20000k ou mais
  • -exec ls -lh {} \; : para cada arquivo que foi encontrado execute ls -lh , ou seja, liste-os em formato longo e tamanho legível (com o sufixo 'K', 'M', 'G', etc.)
  • 2>/dev/null : se find gerou alguma mensagem de erro redirecionando-a para o buraco negro
  • | : canaliza o resultado find para o próximo comando (awk neste caso)
  • awk '{print $NF ": " $5}' : imprime o último campo (da ls -lh output) seguido por dois pontos e, em seguida, seguido pelo quinto campo. O último campo é o nome do arquivo e o quinto campo é o tamanho do arquivo (em formato legível como mencionado anteriormente).
  • | : novamente canalize o resultado (desta vez de awk para sort )
  • sort -hrk 2,2 : resultado da classificação por números legíveis por humanos em ordem inversa, considerando apenas o segundo campo.

Nota

Você pode fazer essa tarefa de maneira muito mais simples e rápida sem os comandos awk e sort :

find / -type f -size +20000k -exec ls -Shs {} +

onde

  • ls -Shs : lista arquivos, imprima seus tamanhos em formato legível e, ao mesmo tempo, classifique-os por tamanho
  • {} + adiciona arquivos encontrados por find à lista e somente no final executa ls na lista inteira. Em {} \; case ls é executado em cada arquivo separadamente.

A única diferença entre esses dois comandos é que, no caso anterior, o tamanho é impresso na segunda coluna, enquanto no segundo, no primeiro. No entanto, se os arquivos ou diretórios tiverem espaços nos nomes, a saída de ls -l terá um número diferente de colunas para cada arquivo, portanto, a saída de awk será mais ou menos aleatória. Em outras palavras, você não deve analisar a saída de ls .

    
por 29.09.2014 / 14:13
3

O

-exec ls -lh {} \;

faz com que o find execute o comando ls -lh em cada arquivo encontrado {} , e ' \; ' indica que cada arquivo é entregue ao comando separadamente. Na página do manual:

   -exec command ;
          Execute command; true if 0 status is returned.   All  following
          arguments  to  find  are  taken  to be arguments to the command
          until an argument consisting of ';' is encountered.  The string
          '{}'  is  replaced  by  the  current  file name being processed
          everywhere it occurs in the arguments to the command, not  just
          in  arguments  where  it is alone, as in some versions of find.
          Both of these constructions might need to be  escaped  (with  a
          '\')  or  quoted  to  protect them from expansion by the shell.
          See the EXAMPLES section for examples of the use of  the  -exec
          option.   The  specified  command  is run once for each matched
          file.  The command  is  executed  in  the  starting  directory.
          There  are unavoidable security problems surrounding use of the
          -exec action; you should use the -execdir option instead.

A parte 2> /dev/null garante que os erros, por ex. para diretórios que não são legíveis, sejam descartados ( /dev/null ).

A saída real de ls -lh para um arquivo é semelhante a:

-rw-rw-r--  1 anthon users   1,2K Aug 24  2013 sizes.data1

e isso vai para o comando awk que extrai o nome do arquivo (NF para o número de campos) e o quinto campo daquele (para o exemplo: sizes.data1: 1.2K )

Esse nome: combinações de tamanho são canalizadas para sort , que classifica no segundo campo ( -k 2,2 ). O -h para ordenação corresponde à saída -h de ls -lh , as ordenações reversas -r .

    
por 29.09.2014 / 14:03
2

-exec ls -lh {} \; 2> /dev/null

Para cada arquivo maior que 20MB executa o comando ls com as opções -l e -h e redireciona os erros para / dev / null.

    -l     use a long listing format

    -h, --human-readable
          with -l, print sizes in human readable format (e.g., 1K 234M 2G)

Isso cria uma saída como:

-rw-r--r--. 1 root root 58M Oct 15 2012 /usr/lib/jvm/java-1.6.0-openjdk-1.6.0.0.x86_64/jre/lib/rt.jar

Comando Awk:

awk '{ print $NF ": " $5 }'

imprime o nome do arquivo com seu tamanho, $ NF significa última coluna e $ 5 significa quinta coluna:

/usr/lib/jvm/java-1.6.0-openjdk-1.6.0.0.x86_64/jre/lib/rt.jar: 58M

E último comando:

sort -hrk 2,2

classifica a segunda coluna, que é o tamanho, ao contrário:

   -h, --human-numeric-sort
          compare human readable numbers (e.g., 2K 1G)
   -r, --reverse
          reverse the result of comparisons
   -k, --key=POS1[,POS2]
          start a key at POS1 (origin 1), end it at POS2 (default end of line)
    
por 29.09.2014 / 14:02
0

Você pode simplificar isso por find's -printf:

find . -type f -size +20k -printf "%h/%f: %kk\n" | sort -hrk 2,2

Mas leia a manpage de encontrar sobre as sutilezas entre% s e% k. (Recusei-me a pesquisar de / e usei para teste. E reduzi o tamanho para + 20k, em vez de + 20M para encontrar qualquer coisa.

    
por 28.02.2018 / 04:18