CSVファイルにリストされているパターンを含むフォルダを検索して別の場所にコピーします。

CSVファイルにリストされているパターンを含むフォルダを検索して別の場所にコピーします。

ファイルを含む数千のフォルダがあり、それらのいくつかを別のディレクトリにコピーしたいと思います。フォルダ名の一部を含む2つの列を持つファイルがあります.csv(フォルダには1つの文字列値が含まれていますが、両方は含まれません)。

  • フォルダ名の例:
    PLASMA_32150129_B5/
    PLASMA_AAA3891784_B3/
    ...
    
  • CSVファイルにはヘッダーがなく、フィールドは次のように区切ります,
    32150129,AAA0616938
    32140203,AAA3891784
    32140204,AAA0617237
    32140205,AAA0617261
    32140206,AAA0617285
    ...
    
  • 私はこの小さなスクリプトを出発点として見つけました。
    while IFS=, read -r file rest
    do
      find /path/to/Main_directory -type d -name "${file}" -exec cp '{}' /path/to/New_directory/ \;
    done < mylist.csv
    

今すぐ指定する必要があります。

  • csv値は単なるパターン(例えば*_32150129 _*)です。
  • まず最初の列のパターンを試してみて、一致するものが生成されない場合は別の列を試してみたいと思います。

可能ですか?

ありがとうございます!

答え1

実際には1つの列しか一致できないと仮定すると、「OR」タイプのアプローチが可能になる可能性があります。これを行うには、スクリプトを少し変更するだけです。

while IFS=, read -r pattern1 pattern2
do
   find /path/to/start -type d \( -name "*_${pattern1}_*" -o -name "*_${pattern2}_*" \) -exec cp -r '{}' /path/to/target \;
done < filelist.csv
  • 演算子は、-o2つの名前パターンのうちの1つが一致することを確認します。 2つが一致しない限り(前提条件を参照)、これは「最初が存在しない場合は2番目」と同じです。
  • 括弧(シェルの解釈を防ぐためにエスケープ)は、正しい演算子の優先順位を確保するために使用されます。
  • シェルパラメータを-name二重引用符で囲むと、*次のことが保証されます。文字通りすぐそこにグローバル拡張は必要なく(findシェルに渡される前ではなく検索中にパターンマッチングを実行する必要がありますfind)、シェル変数${pattern1}${pattern2}拡張が引き続き発生することを許可します。
  • ディレクトリとその内容をコピーするには、-rこのオプションを使用する必要があります。cp

答え2

最も簡単で粗雑な方法を試したことがある場合は、効果があります。一つファイルのすべてのパターンを一致させ、シェルに操作を実行させます。

tr , '\n' < mylist.csv  | 
    while read pat; do cp -r source_dir/*"$pat"* target_dir/ 2>/dev/null; done

まず、すべてを改行,に変換しますfile.csv

$ tr , '\n' < file.csv
32150129
AAA0616938
32140203
AAA3891784
32140204
AAA0617237
32140205
AAA0617261
32140206
AAA0617285

次に、各パターンを変数として読み込み(つまり、マッチのすべての項目)、ターゲットディレクトリに盲目的に$patコピーします。一致するものがないと、何もコピーされず、エラーメッセージが表示され、これにDiscardを使用できます。source_dir/*$pat*source_dir/$pat2>/dev/null


より複雑なアプローチのためには、次のようにすることができます。

## make sure we don't match the glob pattern itself when no matching
## directories are found
shopt -s nullglob

mainTargetDir=/path/to/Main_directory
sourceDir=/path/to/start
while IFS=, read -r f1 f2; do 
    sourceFiles=("$sourceDir"/*"$f1"* "$sourceDir"/*"$f2"*)
    [ -z "${sourceFiles[@]}" ] || 
        cp -r -- "${sourceFiles[@]}" $mainTargetDir 
done < file.csv 

関連情報