何千もの行を含む約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テクノロジがないため、これを達成するためのソリューションを見つけることはありません。
答え2
以前の答えはデータをコピーしてファイルを上書きします。このテクニックは同じinodeを維持してコピーせず、はるかに速く実行する必要があります。各ファイルに対して、次の操作を行います。
(a)最初の200行を読み、各ファイルの長さを取得します。
truncate
truncate
(b)GNU coreutilsまたは一部のBSDシステムのコマンドを使用してファイルをこの長さに切り捨てます。
SZ="$( head -n 200 -- "${file}" | wc -c )"
truncate -s "${SZ}" -- "${file}"
答え3
シェルワイルドカードでsedを使用してください。
sed -ni '1,200p' *.csv
globbing/sed/パラレルを使用してください。
printf '%s\n' *.csv | parallel -- sed -ni '1,200p' {}
.csv
そのディレクトリ内のすべてのファイルを探します。現在のディレクトリGNU Parallelに供給すると、最初の200行だけを維持するようにsedされます。これにより、現在の場所のファイルが上書きされます。
または、パラレルヘッダを使用します。
printf '%s\n' *.csv | parallel -- head -n 200 {} ">" {}.out
.out
これにより、サフィックスを含む新しいファイルが作成されます。
答え4
私は比較的初心者で、優しくしてください。私が提案したソリューションが最適でない場合は、建設的なフィードバックを送っていただきありがとうございます。
たとえば、1から4まで番号が付けられた4つのサンプルファイルを作成しました。touch {1..4}
各ファイルには、最初のファイルの11行から20行までの10行のサンプル行が含まれています。
ファイル1
Line 1
Line 2
Line 3
Line 4
Line 5
Line 6
Line 7
Line 8
Line 9
Line 10
ファイル2
Line 11
Line 12
Line 13
Line 14
Line 15
Line 16
Line 17
Line 18
Line 19
Line 20
抽出の最初の2行(200と推論可能)を例にすると、このコマンドはhead -n 2 {1..4}
出力を返します。
==> 1 <==
Line 1
Line 2
==> 2 <==
Line 11
Line 12
==> 3 <==
Line 21
Line 22
==> 4 <==
Line 31
Line 32
このコマンドは、次のコマンドを使用して出力を別のファイルにリダイレクトできます。head -n 2 {1..4} > ExtractedOutput