tar ファイルのフォルダー内のファイル数を繰り返し計算します。

tar ファイルのフォルダー内のファイル数を繰り返し計算します。

以前の質問をさらに拡張して、tarファイル内のファイル数を計算しました(協会)新しい質問にtarファイルのサブフォルダ内のファイル数を数える方法。私が望む最後のもの:

  1. ファイルを含むフォルダーのリスト
  2. ファイル数の計算以内にそのフォルダ

私の例tarファイルのリスト tar -tvf myfile.tar下のように見える(実際のtarファイルにはより多くのファイルとディレクトリがあります)。合計2つのフォルダがあり、そのうちフォルダ_ファイル_1その中には3つのファイルがあり、フォルダ_ファイル_2その中には4つのファイルがあります。

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

私が検索した最も近い解決策は、使用awk後に私を指していましたtar(参考資料を参照)。ここそしてここ)。

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

/$6/そのフォルダを一致させるだけです./root_folder/subfolder/folder_files_1/。ただし、このファイルに含まれるファイルの数を正確に数えることはまだ不可能です。一致ディレクトリ、すなわち。フォルダ file_1、フォルダ file_2

私のコードを修正する方法に関する提案はありますか?

答え1

別のオプション:

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

最初のawkステートメントはファイル名を削除し、結果のディレクトリパスのインスタンス数を計算します。 2番目は、入力が完全に消費されたときに実行されます(例:標準入力)パスリストとその数を印刷します。

必要に応じて、コンテンツ全体を1行に統合できます(コンテンツ全体をリンクするだけです)。読みやすいようにここで分けました。

tarballに対して実行した結果:

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

答え2

tar -tvf file.tar | grep '^-' | wc -l

tar-(つまり、ファイル)で始まる出力の行数を計算します。アーカイブに特別な種類のファイルがある場合は、/^-「ディレクトリを除くすべてのファイル」を計算するように変更してください。/^[^d]/

別の方法は次のとおりですawk

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

7どちらのコマンドもアーカイブのファイルの総数を出力します。


各サブフォルダに別々の数が必要な場合:

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

これは生成されます

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

あなたが提供するデータ。

最後の例のコードは、awkで始まるすべての行からディレクトリ名を選択dし、それを連想配列のキーとして使用します。見つかったファイルごとに配列エントリが増えます。最後に、すべての項目とその数を印刷します。

答え3

GNU tarがあれば、--to-commandオプション:

--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.

これらの変数を使用すると、スペースなどのファイル名を安全に処理できます。

たとえば、シェル文字列置換を使用して指定されたパスからファイル名を削除し、sedを使用してディレクトリ以外のパスのみを印刷し、それらをソートして適用して数をuniq -c取得できます。

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

GNU sed、sort、およびuniqがある場合は、その-zオプションを使用してすべてのファイル名を安全に処理できprintf "%s %s\0"ますecho

例:

% tar xf dev/pacaur/byobu/byobu_5.124.orig.tar.gz --to-command 'printf "%s %s\0" "$TAR_FILETYPE" "${TAR_FILENAME%/*}"' | sed -zn '/^[^d]/s/^. //p' | sort -z | uniq -zc | tr '\0' '\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

答え4

2回実行しても問題ない場合(最初に数を取得してから行数を取得する)、grepを使用できます。

計算のため:

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

行の場合は削除します。| wc -l

一度だけ実行するには、tar出力をファイルに保存してからcatgrepとwcを使用します。完全なスクリプトは次のとおりです。

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

1行のコードが必要な場合は、プロセスの置き換えとリダイレクトを使用して実行できますが、任意のフローで実行すると、最終的にスクリプト/エイリアス/関数に入れられるため、はるかに簡単に読みやすくなります。 。

tarファイルから複数のパスをgrepするには、そのパスをすべてテキストファイルに入れて、次のものを使用できます。grep -f <paths file>

関連情報