/ command line

แยกไฟล์ใหญ่ๆ ให้เป็นบรรทัดย่อยๆด้วย Command line

พอดีว่าต้อง export ไฟล์ csv ราวๆ 160,000 บรรทัด ได้ไฟล์มาขนาด 200MB ส่งไฟล์ต่อไปให้คนที่ขอ ...เปิดไม่ได้ ไฟล์ใหญ่เกินไป แต่คอมพับผม MacBook Air ใช้ LibreOffice เปิดได้น่ะ


Photo by Ryan Grewell / Unsplash

ก็เลยได้ลองใช้คำสั่ง split ที่อยู่ใน *nix ผมใช้บน Mac OS X (ยังไม่อัปเกรดเป็น macOS เพราะอัปแล้วพังไป 3 รอบ) ขนาดไฟล์ก็เท่านี้

ls -lh export.csv
[email protected] 1 narate staff 237M Sep 2 12:25 export.csv

ไฟล์ขนาด 237MB ก็ใหญ่อยู่น่ะ แต่ไม่ถึงกับว่าใหญ่สัสสส เคย export csv มาไฟล์ 1.x GB ด้วยน่ะ แต่อันนั้นไม่กล้าเอา LibreOffice เปิด 555555 แค่สั่ง cat ยังไม่กล้าเลย มาดูจำนวนบรรทัด

wc -l export.csv
160587 export.csv

มี 160,587 บรรทัด (ตัวแปร A) ผมเลยจะแยกไฟล์ ให้มีสัก 8,000 บรรทัดต่อไฟล์ (ตัวแปร B) ก่อนอื่นเลย ทำการแยก csv บรรทัดที่ 1 ออกไปก่อน โดยใช้คำสั่ง head

head -n1 export.csv > headers.txt

จากนั้นลบบรรทัดที่ 1 ในไฟล์ export.csv ออกด้วยคำสั่ง sed

sed -i '1d' export.csv

ตอนนี้ไฟล์ export.csv จะไม่มีหัวแล้ว คือ csv พิการน่ะ มีแต่ส่วนของข้อมูลล้วนๆ เดี๋ยวค่อยมาประกอบร่างทีหลัง มาแยกร่างมันก่อน ด้วยคำสั่ง split

split -l 8000 export.csv split_

-l 8000 อันนี้คือ จำนวนบรรทัดแต่ละไฟล์
export.csv คือ ชื่อไฟล์
split_ คือ prefix ของไฟล์ที่แตกออกมา ปิ๊ดๆๆ หลังจากรันคำสั่งไป จะได้ไฟล์ชื่อ split_aa, split_ab, ... เรื่อยๆ เช็คดูว่าแต่ละไฟล์ มีกี่บรรทัดด้วยคำสั่ง wc -l

wc -l split_a*

จะได้

    8000 split_aa
    8000 split_ab
    8000 split_ac
    8000 split_ad
    8000 split_ae
    8000 split_af
    8000 split_ag
    8000 split_ah
    8000 split_ai
    8000 split_aj
    8000 split_ak
    8000 split_al
    8000 split_am
    8000 split_an
    8000 split_ao
    8000 split_ap
    8000 split_aq
    8000 split_ar
    8000 split_as
    8000 split_at
     587 split_au
  160587 total

มี 8,000 บรรทัดเกือบทุกไฟล์ ไฟล์สุดท้าย คือเศษที่เหลือจาก A ÷ B ตอนนี้มันก็ยังพิการอยู่ เพราะไม่มีหัวของ csv ทำการรวมมันกลับมาคืน อันนี้คำสั่งยาวหน่อย เขียนมันใส่ไฟล์เป็น shell script แล้วกัน ตั้งชื่อ merge.sh

#!/bin/bash
COUNT=0
for f in split_*
do
  ((COUNT++))
  FILENAME=$(printf "%02d" $COUNT)
  echo "Merging $f..."
  cat headers.txt $f > "export-$FILENAME.csv"
done
echo "done."

คำสั่งก็คือ cat เอา headers.txt ออกมา และ cat ไฟล์ที่ split มาหลังจาก headers.txt แล้ว redirect มันไปใส่ไฟล์ใหม่ ขั้นตอนสุดท้าย คือ รันคำสั่ง เอาง่ายๆเลย

sh merger.sh

จากนั้นจะได้ไฟล์ export-* แล้วเช็คจำนวนบรรทัดของไฟล์ที่ได้

wc -l export-*

จะได้

    8001 export-01.csv
    8001 export-02.csv
    8001 export-03.csv
    8001 export-04.csv
    8001 export-05.csv
    8001 export-06.csv
    8001 export-07.csv
    8001 export-08.csv
    8001 export-09.csv
    8001 export-10.csv
    8001 export-11.csv
    8001 export-12.csv
    8001 export-13.csv
    8001 export-14.csv
    8001 export-15.csv
    8001 export-16.csv
    8001 export-17.csv
    8001 export-18.csv
    8001 export-19.csv
    8001 export-20.csv
     588 export-21.csv
  160608 total

จบ

echo $?

แยกไฟล์ใหญ่ๆ ให้เป็นบรรทัดย่อยๆด้วย Command line
Share this