何千もの行を含む約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
ことを意味します。mv
head
CSVファイルが現在のディレクトリ内のサブディレクトリに散在している場合は、shopt -s globstar
ループのパターンをに置き換えます。これにより、現在のディレクトリ内または下にあるすべてのCSVファイルが見つかり、各ファイルに対して操作が実行されます。ワイルドカードパターンは「再帰的」サブディレクトリと一致しますが、シェルオプションが設定されている場合にのみ適用されます。./*.csv
./**/*.csv
**
globstar
改行を含むデータを含むCSVファイルの場合、レコードが切り捨てられる可能性があるため、上記の方法は正しく機能しません。代わりに、一部のCSV認識ツールを使用して作業を実行する必要があります。
以下は、CSVファイルを解析して通常処理するための一連のコマンドラインツールであるCSVkitとjq
JSONファイルを処理するためのツールを使用しています。
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の他のツールを使用してこの変換を直接実行することは可能かもしれませんが、csvpy
Pythonテクノロジがないため、これを達成するためのソリューションを見つけることはありません。