Número recursivamente de arquivos em pastas no arquivo tar

0

Estou ampliando ainda mais uma pergunta anterior para contar o número de arquivos no arquivo tar ( link ) para uma nova pergunta no como contar arquivos em subpastas em um arquivo tar . O que eu gostaria de ter no final é:

  1. listar as pastas que contêm arquivos
  2. conte o número de arquivos dentro dessa pasta

Meu exemplo lista de arquivos tar tar -tvf myfile.tar se parece com (o arquivo tar real tem mais arquivos e diretórios) . Há um total de 2 pastas onde pasta_files_1 tem 3 arquivos dentro e pasta_files_2 tem 4 arquivos dentro.

drwxrwxrwx someuser/users      0 2017-08-07 11:43 ./root_folder/subfolder/folder_files_1/
-rwxr-xr-x someuser/users 538962 2017-08-07 11:43 ./root_folder/subfolder/folder_files_1/i716266.MRDC.270
-rwxr-xr-x someuser/users 538962 2017-08-07 11:43 ./root_folder/subfolder/folder_files_1/i716267.MRDC.266
-rwxr-xr-x someuser/users 538944 2017-08-07 11:43 ./root_folder/subfolder/folder_files_1/i716268.MRDC.287
drwxrwxrwx someuser/users      0 2017-08-07 11:50 ./root_folder/subfolder/folder_files_2/
-rwxr-xr-x someuser/users 538696 2017-08-07 11:50 ./root_folder/subfolder/folder_files_2/i717157.MRDC.8
-rwxr-xr-x someuser/users 538694 2017-08-07 11:50 ./root_folder/subfolder/folder_files_2/i717158.MRDC.4
-rwxr-xr-x someuser/users 538692 2017-08-07 11:50 ./root_folder/subfolder/folder_files_2/i717159.MRDC.34
-rwxr-xr-x someuser/users 538696 2017-08-07 11:50 ./root_folder/subfolder/folder_files_2/i717160.MRDC.5

A solução mais próxima que eu pesquisei me indicou o uso de awk após tar (consulte as referências aqui e aqui ).

tar tvf myfile.tar | awk '/^d/ {print $0; /$6/; getline; file_no++} END {print file_no}'

/$6/ deve corresponder à pasta correspondente ./root_folder/subfolder/folder_files_1/ . Mas ainda não é preciso contar com precisão os números de arquivos no diretório correspondente , isto é. folder_files_1, _folder_files_2 .

Alguma sugestão sobre como corrigir meu código?

    
por SeanM 06.03.2018 / 19:55

4 respostas

1

Outra opção:

tar tf archive.tar |
    awk '
        { if (gsub("[^/]+$", "")) { h[$0]++} }
        END { for (f in h) { printf "%d\t%s\n", h[f], f } }
    '

A primeira instrução awk retira nomes de arquivos e conta as instâncias dos caminhos de diretório resultantes. O segundo é executado quando a entrada foi totalmente consumida (ou seja, no final de stdin ) e imprime a lista de caminhos e suas respectivas contagens.

A coisa toda pode ser executada em uma única linha se você preferir (literalmente concatenar todo o lote). Eu dividi aqui por legibilidade.

Resultado da execução no seu tarball:

4       ./root_folder/subfolder/folder_files_2/
3       ./root_folder/subfolder/folder_files_1/
    
por 07.03.2018 / 00:44
1
tar -tvf file.tar | grep '^-' | wc -l

Isso contará o número de linhas na saída tar que começam com - (ou seja, arquivos). Altere /^- para /^[^d]/ para contar "tudo menos diretórios" se você tiver tipos especiais de arquivos em seu arquivo.

Outra maneira, com awk :

tar -tvf file.tar | awk '/^-/ { n++ } END { print n }'

Ambos os comandos geram 7 , o número total de arquivos no arquivo.

Se você quiser contagens separadas para cada subpasta:

tar -tvf file.tar | awk '/^d/ { d = $NF; next } { n[d]++ } END { for (d in n) print n[d], d }'

Isso gera

4 ./root_folder/subfolder/folder_files_2/
3 ./root_folder/subfolder/folder_files_1/

para os dados que você forneceu.

O código awk neste último exemplo seleciona o nome do diretório de qualquer linha que comece com d e a use como uma chave em uma matriz associativa. A entrada da matriz é incrementada para cada arquivo encontrado. No final, todas as entradas e suas contagens são impressas.

    
por 06.03.2018 / 20:44
1

Se você tem o GNU tar, ele tem uma --to-command opção:

--to-command=COMMAND
  Pipe extracted files to COMMAND.  The argument is the pathname
  of an external program, optionally with command line
  arguments.  The program will be invoked and the contents of
  the file being extracted supplied to it on its standard
  output.  Additional data will be supplied via the following
  environment variables:

  TAR_FILETYPE
         Type of the file. It is a single letter with the
         following meaning:

                 f           Regular file
                 d           Directory
                 l           Symbolic link
                 h           Hard link
                 b           Block device
                 c           Character device

         Currently only regular files are supported.
  ...
  TAR_FILENAME
         The name of the file.

Essas variáveis podem ser usadas para manipular com segurança nomes de arquivos com espaços, etc.

Por exemplo, usando a substituição de string shell para remover o nome do arquivo do caminho fornecido e, em seguida, usando sed para imprimir somente os caminhos para não diretórios, você pode classificar e aplicar uniq -c para obter a contagem:

tar xf foo.tar --to-command 'echo "$TAR_FILETYPE" "${TAR_FILENAME%/*}"' |
  sed -n '/^[^d]/s/^. //p' | 
  sort |
  uniq -c

Se você tiver o GNU sed, sort e uniq, você pode usar as opções -z e printf "%s %secho" em vez de %code% para manipular com segurança todos os nomes de arquivos.

Exemplo:

% tar xf dev/pacaur/byobu/byobu_5.124.orig.tar.gz --to-command 'printf "%s %s
--to-command=COMMAND
  Pipe extracted files to COMMAND.  The argument is the pathname
  of an external program, optionally with command line
  arguments.  The program will be invoked and the contents of
  the file being extracted supplied to it on its standard
  output.  Additional data will be supplied via the following
  environment variables:

  TAR_FILETYPE
         Type of the file. It is a single letter with the
         following meaning:

                 f           Regular file
                 d           Directory
                 l           Symbolic link
                 h           Hard link
                 b           Block device
                 c           Character device

         Currently only regular files are supported.
  ...
  TAR_FILENAME
         The name of the file.
" "$TAR_FILETYPE" "${TAR_FILENAME%/*}"' | sed -zn '/^[^d]/s/^. //p' | sort -z | uniq -zc | tr '
tar xf foo.tar --to-command 'echo "$TAR_FILETYPE" "${TAR_FILENAME%/*}"' |
  sed -n '/^[^d]/s/^. //p' | 
  sort |
  uniq -c
' '\n' 15 byobu-5.124 2 byobu-5.124/Applications/Byobu.app/Contents 1 byobu-5.124/Applications/Byobu.app/Contents/MacOS 8 byobu-5.124/Applications/Byobu.app/Contents/Resources 4 byobu-5.124/etc/byobu 3 byobu-5.124/etc/profile.d 1 byobu-5.124/experimental 23 byobu-5.124/po 1 byobu-5.124/snap 38 byobu-5.124/usr/bin 43 byobu-5.124/usr/lib/byobu 18 byobu-5.124/usr/lib/byobu/include 1 byobu-5.124/usr/share/appdata 4 byobu-5.124/usr/share/byobu/desktop 12 byobu-5.124/usr/share/byobu/keybindings 4 byobu-5.124/usr/share/byobu/pixmaps 1 byobu-5.124/usr/share/byobu/pixmaps/highcontrast 11 byobu-5.124/usr/share/byobu/profiles 4 byobu-5.124/usr/share/byobu/status 3 byobu-5.124/usr/share/byobu/tests 3 byobu-5.124/usr/share/byobu/windows 3 byobu-5.124/usr/share/dbus-1/services 4 byobu-5.124/usr/share/doc/byobu 37 byobu-5.124/usr/share/man/man1 1 byobu-5.124/usr/share/sounds/byobu
    
por 07.03.2018 / 07:54
0

Se você não se importar em executá-lo duas vezes (para obter a contagem, então as linhas), você pode usar o grep.

Para a contagem:

tar tvf myfile.tar | grep <path> | wc -l

Para as linhas, basta remover o | wc -l

Se você preferir executar apenas tar uma vez, poderá salvar a saída em um arquivo e, em seguida, cat para grep e wc. O roteiro todos juntos seria algo como isto:

tmp_file=$(mktemp)
tar tvf myfile.tar > $tmp_file
cat $tmp_file | grep <subdir> | wc -l
cat $tmp_file | grep <subdir>
rm $tmp_file

Se você quer um one-liner, provavelmente existe um hack que você pode fazer com o processo de substituição e redirecionamento, mas se você estiver rodando com alguma cadência, provavelmente acabará colocando-o em um script / alias / function isso é um pouco mais fácil de ler e entender.

Se você tiver vários caminhos no arquivo tar que deseja extrair, coloque-os todos em um arquivo de texto e use grep -f <paths file>

    
por 06.03.2018 / 20:28

Tags