bashを使用してディレクトリ内のすべてのcsvファイルの最初の200行を保持する方法は?

bashを使用してディレクトリ内のすべてのcsvファイルの最初の200行を保持する方法は?

何千もの行を含む約50の非常に大きなcsvファイルがあります。

各ファイルの最初の200行だけを維持したいと思います。生成されたファイルが元のファイルを上書きしても問題はありません。

これを行うにはどのコマンドを使用する必要がありますか?

ベストアンサー1

現在、ディレクトリにすべてのCSVファイルが含まれており、すべて.csvファイル名のサフィックスがあるとします。

for file in ./*.csv; do
    head -n 200 "$file" >"$file.200"
done

headこれにより、リダイレクトを使用して各CSVファイルの最初の200行が新しいファイルに出力されます。新しいファイルの名前は古いファイルと同じですが、.200名前の末尾に追加されます。新しいファイル名がすでに存在するかどうかは確認されません。

元のものを交換したい場合:

for file in ./*.csv; do
    head -n 200 "$file" >"$file.200" &&
    mv "$file.200" "$file"
done

コマンド&&の最後には、実行中に問題があると実行されないheadことを意味します。mvhead

CSVファイルが現在のディレクトリ内のサブディレクトリに散在している場合は、shopt -s globstarループのパターンをに置き換えます。これにより、現在のディレクトリ内または下にあるすべてのCSVファイルが見つかり、各ファイルに対して操作が実行されます。ワイルドカードパターンは「再帰的」サブディレクトリと一致しますが、シェルオプションが設定されている場合にのみ適用されます。./*.csv./**/*.csv**globstar


改行を含むデータを含むCSVファイルの場合、レコードが切り捨てられる可能性があるため、上記の方法は正しく機能しません。代わりに、一部のCSV認識ツールを使用して作業を実行する必要があります。

以下は、CSVファイルを解析して通常処理するための一連のコマンドラインツールであるCSVkitとjqJSONファイルを処理するためのツールを使用しています。

CSVファミリには、特定のポイントでCSVファイルを切り取るためのツールはありませんが、CSVファイルをJSONに変換してそれを使用してjq最初の200レコードのみを出力できます。

for file in ./*.csv; do
    csvjson -H "$file" | jq -r '.[:200][] | map(values) | @csv' >"$file.200" &&
    mv "$file.200" "$file"
done

以下の短い例のように、いくつかのCSVファイルが与えられた場合

a,b,c
1,2,3
"hello, world",2 3,4
"hello
there","my good
man",nice weather for ducks

このcsvjsonコマンドは生成されます

[
  {
    "a": "a",
    "b": "b",
    "c": "c"
  },
  {
    "a": "1",
    "b": "2",
    "c": "3"
  },
  {
    "a": "hello, world",
    "b": "2 3",
    "c": "4"
  },
  {
    "a": "hello\nthere",
    "b": "my good\nman",
    "c": "nice weather for ducks"
  }
]

その後、ツールjqはこのデータを取得し、配列内の各オブジェクト(最初の200個のオブジェクトのみ)に対して値を配列に抽出し、それをCSVにフォーマットします。

CSVkitの他のツールを使用してこの変換を直接実行することは可能かもしれませんが、csvpyPythonテクノロジがないため、これを達成するためのソリューションを見つけることはありません。

おすすめ記事