Unixコマンドを使用して、異なるフォルダにある類似の名前を持つ複数のファイルをマージする方法は?

Unixコマンドを使用して、異なるフォルダにある類似の名前を持つ複数のファイルをマージする方法は?

私はこの質問を以前に尋ねて答えたことがあることを知っています。コードを試しましたが、正しい出力を取得できませんでした。

vanila1とvanila2という2つのフォルダがあります。各フォルダには、同じ名前の400個のファイルがあります。

ls vanila1
MB.2613.007_0021.ED4_KS1A29-7_338_all
MB.2613.007_0022.ED9_SD2A27-1_180_all
MB.2613.007_14.ED14_IA2A35-2_310_all

ls vanila2
MB.2613.007_0021.ED4_KS1A29-7_338_all
MB.2613.007_0022.ED9_SD2A27-1_180_all
MB.2613.007_14.ED14_IA2A35-2_310_all

同じ名前のファイルをマージしたいです。以下を使用しています。

ls vanila1 | while read FILE; do
  cat vanila1/"$FILE" vanila2/"$FILE" >> all_combined/"$FILE"
done

正しい出力が出ません。結合されたファイルの行数がfile1とfile2の合計よりも大きいです。私は何が間違っていましたか?

答え1

おそらくループを何度も実行しているようです。>>リダイレクト演算子を使用しているので追加結果ファイルは毎回大きくなります。

代わりに(私はここでも使用しませんls。」なぜ`ls`を解析しないのですか?「理由で):

for name in vanila1/*; do
    base_name=${name##*/}

    if [ -f "vanila2/$base_name" ]; then
        cat "$name" "vanila2/$base_name" >"all_combined/$base_name"
    else
        printf 'No file in vanila2 corresponds to "%s"\n' "$name" >&2
    fi
done

変数置換は${name##*/}パス名vanila1/MB.2613.007_0021.ED4_KS1A29-7_338_allをに変換します。つまり、スラッシュ(パス名のファイル名コンポーネントまたは「デフォルト名」)など、MB.2613.007_0021.ED4_KS1A29-7_338_allその前のすべてを削除します。/この製品は交換できます$(basename "$name")

vanila2からインポートされた名前に対応するファイルが存在する場合は、vanila12つのファイルが関連付けられてall_combinedそのディレクトリに配置されます。そうでない場合は、この事実に関する診断メッセージが表示されます。

>代わりにを使用すると、同じ名前の>>既存all_combinedのファイルが追加されるのではなく置き換えられます。


お持ちの場合その他のファイルあるいは、ディレクトリの場合は、関心のあるファイル(または類似のファイルなど)のみが一致するようにvanila1ループのパターンを変更できます。vanila1/*vanila1/*_all

答え2

それでは、2つのディレクトリに同じ名前のファイルがありますが、2つのファイルを関連付けることができる2つのファイルはどこにありますか?

for file in dir1/*; do
   otherfile="$(basename "$file")"
   if [[ -r dir2/"${otherfile}" ]]; then
       cat "$file" dir2/"$otherfile" >> combined/"$otherfile"
   fi
done

関連情報