Linux cho DE 2 — Điều hướng & thao tác file

13 thg 7, 2026 3 lượt xem
#devops
#linux
#navigation
#filesystem
#cli

Vì sao DE phải thành thạo thao tác file trên terminal

Là data engineer, phần lớn thời gian bạn không "click chuột" mà gõ lệnh trên một server không có giao diện đồ hoạ: SSH vào edge node của cụm Spark, vào máy chứa Airflow worker, vào bastion host để kéo dataset về. Ở đó chỉ có shell. Một pipeline điển hình sinh ra hàng nghìn file: part-00000.parquet, application_2026-06-*.log, export_20260630.csv.gz. Bạn cần đếm dòng, kiểm tra dung lượng, tìm file cũ để dọn, nén dataset trước khi chuyển qua mạng. Toàn bộ đều làm bằng vài lệnh cơ bản — làm nhanh hay chậm quyết định bởi bạn nắm chắc chúng đến đâu.

Bài này đi từ điều hướng đến thao tác, tìm kiếm, kiểm tra và nén — kèm ví dụ với thư mục dữ liệu thật. Nếu bạn chưa đọc phần tổng quan, xem Linux cho DE 1.

Điều hướng: bạn đang ở đâu, có gì quanh đây

Ba lệnh nền tảng: pwd (in thư mục hiện tại — print working directory), cd (đổi thư mục — change directory), ls (liệt kê — list).

pwd
# /data/warehouse/raw/transactions

cd /data/warehouse/raw/transactions/2026/06
ls

ls trần trụi chỉ cho tên file. Sức mạnh nằm ở các flag, và chúng gộp được với nhau:

FlagÝ nghĩaDùng khi
-ldạng dài: quyền, chủ sở hữu, kích thước, thời gianxem chi tiết
-ahiện cả file ẩn (bắt đầu bằng .)tìm .env, .gitignore
-hkích thước dễ đọc (K/M/G) — đi kèm -lxem file to nhỏ
-tsắp theo thời gian sửa, mới nhất trêntìm file vừa sinh
-rđảo thứ tựmới nhất xuống cuối
-Rđệ quy, vào cả thư mục consoi cả cây
-Ssắp theo kích thướctìm file nặng nhất
# File parquet mới nhất nằm trên cùng, kích thước dễ đọc
ls -lht

# Toàn bộ, kể cả file ẩn, sắp theo kích thước giảm dần
ls -lahS

# 5 file mới nhất trong thư mục output của một job
ls -lt /data/spark/output | head -6

Đọc một dòng ls -l:

-rw-r--r-- 1 airflow airflow 2.3G Jun 30 02:14 transactions.parquet

Ký tự đầu - là file thường (nếu là d thì là thư mục, l là symlink). Tiếp theo là quyền, số link, chủ sở hữu (airflow), nhóm, kích thước (2.3G nhờ -h), thời gian sửa, tên. Chi tiết về cột quyền sẽ nói ở bài quyền & user.

Đường dẫn: tuyệt đối và tương đối

Đường dẫn tuyệt đối bắt đầu bằng / (thư mục gốc), luôn trỏ đúng một chỗ bất kể bạn đang đứng đâu: /data/warehouse/raw/transactions. Đường dẫn tương đối tính từ thư mục hiện tại, không bắt đầu bằng /.

Bốn ký hiệu tắt phải thuộc lòng:

Ký hiệuNghĩa
.thư mục hiện tại
..thư mục cha (lùi một cấp)
~home của bạn (/home/airflow)
-thư mục trước đó (cd - để nhảy qua lại)
cd /data/warehouse/raw/transactions/2026/06
cd ..            # lên /data/warehouse/raw/transactions/2026
cd ../../curated # lùi 2 cấp rồi vào curated → /data/warehouse/raw/curated
cd ~/scripts     # về ~/scripts bất kể đang ở đâu
cd -             # nhảy lại thư mục ngay trước đó

Mẹo: cd không tham số sẽ về thẳng home. Dùng cd - để "toggle" giữa hai thư mục khi bạn vừa copy file bên A vừa kiểm tra bên B.

Cây thư mục dữ liệu điển hình và các đường đi:

Nếu đang ở 06, đi sang curated bằng tương đối: cd ../../../../curated/daily_balance — nhưng nói thật, đường tuyệt đối cd /data/warehouse/curated/daily_balance dễ đọc hơn nhiều. Quy tắc thực chiến: trong script dùng đường tuyệt đối cho chắc chắn; gõ tay thì tương đối cho nhanh.

Thao tác file: tạo, sao chép, di chuyển, xoá

mkdir staging                 # tạo 1 thư mục
mkdir -p data/2026/06/day30   # -p: tạo cả chuỗi cha, không báo lỗi nếu đã có
touch manifest.txt            # tạo file rỗng, hoặc cập nhật timestamp file có sẵn

cp report.csv report_bak.csv  # sao chép 1 file
cp -r raw/ raw_backup/        # -r: sao chép đệ quy cả thư mục
cp -a raw/ raw_backup/        # -a: giữ nguyên quyền, thời gian, symlink (archive)

mv old_name.csv new_name.csv  # đổi tên (mv = move)
mv *.parquet /data/curated/   # di chuyển nhiều file

mkdir -p cực hữu ích trong script: tạo đường dẫn phân vùng theo ngày mà không cần kiểm tra thư mục cha đã tồn tại chưa. touch ngoài việc tạo file rỗng còn dùng để tạo file cờ (marker) như _SUCCESS — chuẩn Spark/Hadoop báo job xong.

rm -rf — lệnh nguy hiểm nhất bạn sẽ gõ

rm file.csv          # xoá 1 file
rm -r old_dir/       # xoá thư mục và mọi thứ bên trong
rm -f locked.tmp     # ép xoá, không hỏi
rm -rf /data/tmp/*   # xoá tất cả trong /data/tmp

Trên Linux không có thùng rácrm xoá vĩnh viễn, không undo. rm -rf (recursive + force) là công cụ quét sạch, và cũng là công cụ xoá sạch sự nghiệp nếu gõ sai. Các nguyên tắc sống còn:

  • Không bao giờ để dấu cách lạc giữa đường dẫn. rm -rf /data /tmp (thừa dấu cách) sẽ xoá cả /data.
  • Cảnh giác biến rỗng: rm -rf "$DIR/"* — nếu $DIR chưa được set, lệnh biến thành rm -rf /*. Trong script luôn set -u để lỗi ngay khi biến chưa định nghĩa.
  • Xem trước bằng ls: gõ ls /data/tmp/* xác nhận đúng danh sách rồi mới đổi ls thành rm.
  • Trên production, cân nhắc -i (hỏi từng file) hoặc chuyển file vào thư mục .trash/ rồi cron dọn sau, thay vì xoá thẳng.

Wildcard & globbing: nói với shell "tất cả các file kiểu này"

Shell tự động khai triển các ký tự đặc biệt thành danh sách tên file trước khi chạy lệnh. Đây là globbing, khác regex.

MẫuKhớpVí dụ
*0 hoặc nhiều ký tự bất kỳ*.parquet → mọi file parquet
?đúng 1 ký tựlog_?.txtlog_1.txt, log_a.txt
[...]1 ký tự trong tậpdata_[0-9].csv
[!...]1 ký tự KHÔNG trong tập[!_]* → tên không bắt đầu bằng _
{a,b}luân phiên (brace expansion)part-{00,01,02}.parquet
ls *.csv                         # mọi file CSV trong thư mục hiện tại
ls part-000[0-9][0-9].parquet    # part-00000 đến part-00099
cp export_{2026,2025}.csv /bak/  # copy đúng 2 file
rm application_2026-06-*.log     # xoá mọi log tháng 6/2026
ls **/**.parquet                 # (nếu bật globstar) parquet ở mọi cấp con

Lưu ý quan trọng: nếu *.csv không khớp file nào, shell mặc định để nguyên chuỗi *.csv truyền vào lệnh — dễ gây lỗi khó hiểu. Và {...}brace expansion — sinh chuỗi kể cả khi không có file tương ứng (khác *). Với dữ liệu, hãy nhớ globbing chỉ nhìn tên file, không nhìn nội dung.

Tìm file: findlocate

find là con dao đa năng — duyệt cây thư mục theo điều kiện. Cú pháp: find <nơi bắt đầu> <điều kiện> <hành động>.

Theo tên:

find /data/warehouse -name "*.parquet"        # phân biệt hoa thường
find /data/warehouse -iname "*.CSV"           # -i: không phân biệt hoa thường
find . -type d -name "day*"                   # -type d: chỉ thư mục
find . -type f -name "part-*"                 # -type f: chỉ file

Theo kích thước:

find /data -size +1G                          # lớn hơn 1 GB
find /data -size +100M -size -1G              # từ 100MB đến 1GB
find /tmp -size 0                             # file rỗng (0 byte)

Theo thời gian (-mtime theo ngày, -mmin theo phút; +n = cũ hơn, -n = mới hơn):

find /data/logs -name "*.log" -mtime +7       # sửa cách đây hơn 7 ngày
find /data/output -mmin -60                   # thay đổi trong 60 phút qua

Kết hợp hành động với -exec ({} là file tìm thấy, \; kết thúc lệnh):

# Đếm dòng từng CSV lớn tìm được
find /data -name "*.csv" -size +10M -exec wc -l {} \;

# Xoá log cũ hơn 30 ngày (dọn ổ đĩa định kỳ)
find /data/logs -name "*.log" -mtime +30 -delete

# Nén mọi CSV cũ để tiết kiệm chỗ
find /archive -name "*.csv" -mtime +90 -exec gzip {} \;

Dùng + thay \; để gom nhiều file vào một lần gọi lệnh (nhanh hơn nhiều với hàng nghìn file): find . -name "*.log" -exec rm {} +.

locate khác find: nó tra một database index (cập nhật bởi updatedb, thường chạy hàng ngày) nên trả kết quả tức thì nhưng có thể lỗi thời:

locate transactions.parquet    # nhanh, nhưng file vừa tạo có thể chưa có trong index
sudo updatedb                  # cập nhật index thủ công

Quy tắc: find khi cần chính xác thời gian thực và điều kiện phức tạp; locate khi chỉ muốn "file này nằm đâu" và cần nhanh.

Kiểm tra file: nó là gì, to bao nhiêu, còn bao nhiêu chỗ

file export.dat        # đoán loại file thật (không tin đuôi tên)
# export.dat: gzip compressed data

file đọc magic bytes để nhận diện — rất hữu ích khi nhận file không rõ định dạng (một .txt thực chất là gzip, một .csv thực ra là UTF-16).

stat transactions.parquet
# Size, quyền, thời gian Access/Modify/Change, số inode

Dung lượng — cặp lệnh DE dùng hàng ngày:

du -sh /data/warehouse/raw/transactions   # -s tổng, -h dễ đọc → "142G"
du -sh */                                 # dung lượng từng thư mục con
du -h --max-depth=1 /data | sort -rh      # xếp hạng thư mục nặng nhất

df -h                                     # dung lượng còn trống theo phân vùng
df -h /data                               # riêng phân vùng chứa /data

du (disk usage) đo file/thư mục; df (disk free) đo phân vùng. Khi job Spark chết vì "No space left on device", phản xạ đầu tiên là df -h xem phân vùng nào đầy, rồi du -sh */ | sort -rh truy thư mục nào ngốn chỗ.

Đếm dòng dữ liệu:

wc -l transactions.csv          # số dòng (gồm cả header)
wc -l *.csv                     # từng file + tổng
cat data/*.csv | wc -l          # tổng dòng nhiều file

wc -l là cách nhanh nhất kiểm tra số bản ghi một file CSV/TSV. Nhớ trừ 1 dòng header khi so với số record thật. (Không dùng được trực tiếp cho parquet vì đó là định dạng nhị phân — cần công cụ như parquet-tools hay đọc bằng Python/DuckDB.)

Xem đầu/cuối file lớn: headtail

Với file CSV/log hàng GB, đừng bao giờ cat cả file (treo terminal). Xem một phần:

head transactions.csv           # 10 dòng đầu (mặc định)
head -5 transactions.csv        # 5 dòng đầu — kiểm tra header + vài record
tail transactions.csv           # 10 dòng cuối
tail -100 app.log               # 100 dòng cuối của log

tail -f app.log                 # -f: theo dõi log ĐANG chạy, dòng mới hiện realtime
tail -f app.log | grep ERROR    # lọc lỗi trực tiếp khi job chạy

tail -f (follow) là bạn thân khi debug: mở một terminal chạy job, terminal khác tail -f để xem log tuôn ra. Kết hợp head/tail để cắt lát giữa: head -1000 big.csv | tail -100 lấy dòng 901–1000. Xử lý text sâu hơn (grep, awk, cut) sẽ ở bài xử lý văn bản, còn ghép lệnh bằng pipe ở bài pipe & redirection.

Symbolic link (ln -s) là một "lối tắt" trỏ tới file/thư mục thật. Rất hay dùng để tạo con trỏ "latest" ổn định trong khi dữ liệu thật đổi theo ngày:

ln -s /data/warehouse/curated/2026/06/30 /data/warehouse/curated/latest
ls -l /data/warehouse/curated/latest
# lrwxrwxrwx ... latest -> /data/warehouse/curated/2026/06/30

Job downstream chỉ cần đọc .../curated/latest; mỗi ngày bạn trỏ lại symlink sang phân vùng mới là xong, không phải sửa cấu hình. Cập nhật symlink an toàn (nguyên tử): ln -sfn /data/.../07/01 latest (-f ghi đè, -n không đi vào thư mục đích cũ). Xoá symlink bằng rm latest chỉ xoá link, không đụng dữ liệu thật — nhưng cẩn thận rm -r latest/ (có dấu /) có thể xoá nội dung đích.

Nén & giải nén: sống còn khi chuyển dataset

Chuyển 50GB CSV qua mạng nội bộ mà không nén là phí băng thông và thời gian. Ba công cụ chính:

tar — gom nhiều file/thư mục thành một archive (thường kèm nén):

tar -czf backup.tar.gz /data/warehouse/curated/2026/06   # c=create z=gzip f=file
tar -xzf backup.tar.gz                                    # x=extract
tar -tzf backup.tar.gz                                    # t=list, xem nội dung
tar -xzf backup.tar.gz -C /restore/here                   # -C: giải vào thư mục đích

Mẹo nhớ: create, extract, table-of-contents; luôn thêm z cho gzip và f trước tên file. Muốn nén mạnh hơn dùng -j (bzip2) hoặc -J (xz) — chậm hơn nhưng file nhỏ hơn.

gzip — nén từng file riêng lẻ (thay thế file gốc):

gzip transactions.csv          # → transactions.csv.gz, XOÁ bản gốc
gunzip transactions.csv.gz     # giải nén lại
gzip -k transactions.csv       # -k: giữ cả bản gốc
zcat transactions.csv.gz | head  # xem nội dung mà không giải nén ra đĩa

zcat/zgrep cho phép đọc/grep file .gz trực tiếp — cực tiện với log nén: zgrep "ERROR" app_2026-06-30.log.gz.

zip — định dạng phổ biến khi trao đổi với Windows/người dùng nghiệp vụ:

zip -r report.zip report/      # -r: gồm cả thư mục con
unzip report.zip               # giải nén
unzip -l report.zip            # -l: liệt kê nội dung không giải

So sánh nhanh cho DE:

Công cụGom nhiều file?Ghi đè bản gốc?Khi nào dùng
tar -czfKhông (tạo archive mới)đóng gói cả thư mục dataset
gzipKhông (1 file/lần)Có (trừ khi -k)nén từng file lớn, log
zipKhônggửi cho người dùng Windows

Lưu ý: parquet đã nén sẵn bên trong (Snappy/GZIP), nên gzip lại một file parquet gần như vô ích — chỉ nên nén CSV/JSON/log là những định dạng text chưa nén.

Use case thực tế

Bối cảnh: Tổ Vận hành dữ liệu NCB nhận cảnh báo phân vùng /data còn 4% trống trên edge node của cụm Spark. Job ETL giao dịch thẻ nửa đêm bắt đầu fail với "No space left on device". Cần khắc phục trong ca trực.

Bước 1 — Xác định phân vùng đầy:

df -h /data
# /dev/sdb1  2.0T  1.92T  80G  96% /data

Bước 2 — Truy thư mục ngốn chỗ:

du -h --max-depth=1 /data | sort -rh | head
# 1.1T  /data/warehouse/raw
# 640G  /data/logs
# 180G  /data/tmp

/data/logs phình bất thường tới 640G.

Bước 3 — Tìm log cũ và ước lượng:

find /data/logs -name "*.log" -mtime +30 -type f | wc -l
# 8214   → hơn 8000 file log cũ hơn 30 ngày
du -sh $(find /data/logs -name "*.log" -mtime +30)  2>/dev/null | tail -1

Bước 4 — Nén thay vì xoá (log còn cần cho audit AML — xem STR reporting — nên nén để giữ chứng cứ, giảm dung lượng ~85%):

find /data/logs -name "*.log" -mtime +30 -exec gzip {} +

Bước 5 — Dọn thư mục tạm an toàn (sau khi ls xác nhận):

ls /data/tmp/spark-*         # xác nhận đúng thư mục tạm của Spark
find /data/tmp -maxdepth 1 -name "spark-*" -mtime +1 -exec rm -rf {} +

Bước 6 — Kiểm tra lại và trỏ symlink dataset đã archive:

df -h /data                  # còn trống trở lại ~28%

Kết quả: giải phóng ~560G trong 15 phút, không mất dữ liệu audit, job ETL chạy lại thành công. Toàn bộ quy trình sau đó được đưa vào một cron job dọn dẹp định kỳ (xem lập lịch & systemd).

Ghi nhớ

  • pwd/cd/ls là bộ ba nền tảng; ls -lht (chi tiết, dễ đọc, mới nhất trên) là combo dùng nhiều nhất khi soi output pipeline.
  • Đường dẫn tuyệt đối (/...) cho script để chắc chắn; tương đối (. .. ~ -) cho gõ tay cho nhanh. cd - nhảy qua lại 2 thư mục.
  • mkdir -p tạo cả chuỗi thư mục cha; touch tạo file rỗng/marker; cp -r/cp -a sao chép thư mục.
  • rm -rf xoá vĩnh viễn, không thùng rác: luôn ls xem trước, set -u trong script, cảnh giác dấu cách lạc và biến rỗng.
  • Globbing (* ? [] {}) khai triển tên file trước khi chạy lệnh — khác regex, chỉ nhìn tên không nhìn nội dung.
  • find cho tìm kiếm chính xác theo tên/kích thước/thời gian và hành động -exec; locate cho tra nhanh qua index (có thể lỗi thời).
  • du -sh đo file/thư mục, df -h đo phân vùng còn trống — bộ đôi xử lý sự cố hết ổ đĩa. wc -l đếm dòng CSV nhanh.
  • File lớn dùng head/tail (đừng cat); tail -f theo dõi log realtime.
  • ln -s tạo symlink "latest" ổn định cho downstream; cập nhật bằng ln -sfn.
  • Nén khi chuyển dataset: tar -czf gói cả thư mục, gzip nén từng file, zip khi gửi Windows. Parquet đã nén sẵn — đừng gzip lại.

Bài viết liên quan

Bản chất DevOps: phá bỏ rào cản Dev–Ops, vòng lặp vô tận, CALMS, và vì sao tự động hoá.

13 thg 7, 2026 3

Continuous Integration/Delivery/Deployment, cấu trúc pipeline, ví dụ GitHub Actions và chiến lược release.

13 thg 7, 2026 3

Container vs máy ảo, image/layer, Dockerfile, volume, network, Docker Compose và best practices.

13 thg 7, 2026 3

Ba trụ cột logging–metrics–tracing, Prometheus/Grafana, alerting, SLI/SLO/SLA và golden signals.

13 thg 7, 2026 3