複数のサブフォルダにある同じ名前のファイルをマージする

複数のサブフォルダにある同じ名前のファイルをマージする

多くのファイルを含む複数のフォルダがあり、各フォルダには同じ名前のtxtファイルがあり、同じ名前のファイルを1つのtxtファイルにマージしたいと思います。

例:

folder/
     -sub1
     -sub2
     -sub3
      .
      .
      .
     -sub28

各サブフォルダには複数のファイルがあります。

EAF001.ID001.txt  EAF001.ID002.txt  EAF001.ID003.txt  EAF001.ID004.txt
EAF001.ID005.txt  EAF001.ID006.txt  EAF001.ID007.txt  EAF001.ID008.txt
EAF001.ID009.txt  EAF001.ID010.txt  EAF001.ID011.txt  EAF001.ID012.txt
EAF001.ID013.txt  EAF001.ID014.txt  EAF001.ID015.txt  EAF001.ID016.txt

同じ名前のファイルをマージしたいです。

EAF001.ID001.merge.txt  EAF001.ID002.merge.txt  EAF001.ID003.merge.txt  EAF001.ID004.merge.txt
EAF001.ID005.merge.txt  EAF001.ID006.merge.txt  EAF001.ID007.merge.txt  EAF001.ID008.merge.txt
EAF001.ID009.merge.txt  EAF001.ID010.merge.txt  EAF001.ID011.merge.txt  EAF001.ID012.merge.txt
EAF001.ID013.merge.txt  EAF001.ID014.merge.txt  EAF001.ID015.merge.txt  EAF001.ID016.merge.txt

どんな助けでも大変感謝します。

答え1

export dir='/path/to/folder'

find "$dir" -mindepth 2 -type f -name 'EAF*.txt' \
  -exec sh -c 'for f; do
                 bn=$(basename "$f" .txt);
                 cat "$f" >> "$dir/$bn.merged.txt";
               done' sh {} +

この-mindepth 2オプションは、/path/to/folder ディレクトリ自体のファイルを処理から除外します (つまり、サブディレクトリ内のファイルのみを検索する)、出力ファイルが既に存在する場合、出力ファイルはそれ自体に関連付けられません。

重複したファイル名があるかどうかに関係なく、「merged.txt」出力ファイルにファイルが追加されます。

重複したファイル名のみをマージしたい場合:

typeset -Ax counts # declare $counts to be an exported associative array
export dir='/path/to/folder'

# find out how many there are of each filename
while read -d '' -r f; do
  let counts[$f]++;
done < <(find "$dir" -mindepth 2 -type f -name 'EAF*.txt' -print0)

# concatenate only the duplicates
find "$dir" -mindepth 2 -type f -name 'EAF*.txt' \
  -exec bash -c 'for f; do
                   if [ "${counts[$f]}" -gt 1 ]; then
                     bn=$(basename "$f" .txt);
                     cat "$f" >> "$dir/$bn.merged.txt";
                   fi
                 done' sh {} +

これには、bash連想配列をサポートする他のシェル(POSIXなどsh)が必要です。

答え2

findtxtファイルを繰り返して、重複した名前を使用して計算できますwc。重複する名前の数が1より大きい場合は、merge.txtファイルに追加されます。

#!/bin/bash

output_dir="output"
rm -rf "$output_dir"
mkdir "$output_dir"

for file in */*.txt; do
  file_name=$(basename "$file" .txt)
  duplicate_names_count=$(find . -type f -name "$file_name.txt" |  wc -l)
  if [ "$duplicate_names_count" -gt 1 ]; then
    cat "$file" >> "$output_dir/${file_name}.merge.txt"
  fi
done

関連情報