Học bằng cách đọc theo thứ tự

Vòng lặp — for xử lý từng tệp một

Bài viết này là một phần của Khóa học Linux, giúp bạn thành thạo từ đầu những kỹ năng Linux thực tiễn, từ các lệnh cơ bản đến lập trình shell script.
Lặp qua danh sách tệp bằng for f in *.txt, lặp có điều kiện bằng while [ "$i" -le 3 ] và until, bỏ qua giá trị rỗng bằng continue, và dừng tại giới hạn bằng break — minh họa và thực hành trên terminal trong trình duyệt.

Xử lý lần lượt một danh sách — for

for lấy từng giá trị bạn đưa vào và chạy cùng một công việc trên mỗi cái.

Dạng của nó là for v in a b c; do ... done, trong đó v lần lượt nhận a, rồi b, rồi c.

Phần nằm giữa dodone là phần thân được lặp lại.

Bạn có thể liệt kê trực tiếp các giá trị, dùng một mẫu tệp như *.txt, hoặc đưa vào đầu ra của $(...) từ một lệnh.

Viết for f in *.txt thì mỗi tệp .txt trong thư mục hiện tại lần lượt đi vào f, nên bạn có thể viết xử lý cho từng tệp.

Dùng $(...) như trong for line in $(cat list.txt) cho phép bạn lặp qua đầu ra của một lệnh.

Đây là cách bạn viết việc tổng hợp một danh sách tệp hoặc xử lý hàng loạt trên nhiều tệp.

for env in dev stg prod; do        # xử lý lần lượt các giá trị đã liệt kê
  echo "deploying to $env"
done
for f in *.sh; do                  # xử lý lần lượt các tệp .sh
  echo "script: $f"
done
Cách một vòng lặp for chạy
for f in *.txtChạy phần thân(do … done)phần tử kế → fkết thúc tại donekhi hết phần tửlặp cho mỗi phần tử
for lần lượt lấy từng phần tử trong danh sách vào f và chạy phần thân, rồi kết thúc tại done khi các phần tử đã hết.
SyntaxÝ nghĩaExample
for v in a b c; do … donexử lý lần lượt các giá trị đã liệt kêfor v in dev stg prod; do echo $v; done
for f in *.txt; do …xử lý lần lượt các tệp khớpfor f in *.txt; do wc -l "$f"; done
for x in $(cmd); do …xử lý lần lượt đầu ra của lệnhfor d in $(ls); do echo $d; done
do … donebắt đầu và kết thúc phần thân vòng lặpfor v in a b; do echo $v; done

Viết một script lặp qua danh sách tệp và tổng hợp số đếm.

① Mở count-lines.sh bằng vi count-lines.sh, nhấn i để vào insert mode, và viết #!/bin/sh ở dòng đầu tiên.

② Trong script, tạo vài tệp nguyên liệu, lặp một mẫu tệp bằng for, đếm số dòng của từng tệp một, và in ra tổng.

③ Nhấn Esc, lưu bằng :wq, rồi thêm quyền thực thi.

④ Chạy script và xác nhận rằng mỗi tệp và tổng được in ra.

⑤ Nếu bạn chưa chắc nên viết gì, hãy sao chép nội dung trong bảng đáp án rồi dán vào insert mode của vi. (Chạy đúng để hiện phần giải thích.)

Linux console
0 / 3 đã hoàn thành
Loading Linux Terminal...

Lặp theo điều kiện — while / until

while lặp lại chừng nào điều kiện còn đúng.

Như trong while [ "$i" -lt 3 ]; do ... done, bạn tăng một biến đếm bên trong phần thân để tiến dần đến lúc kết thúc.

until thì ngược lại — nó lặp cho đến khi điều kiện trở thành đúng.

Nó phù hợp với việc mà số vòng không được biết trước.

i=1
while [ "$i" -le 3 ]; do          # lặp chừng nào i nhỏ hơn hoặc bằng 3
  echo "try $i"
  i=$((i + 1))
done                              # try 1 / try 2 / try 3
i=1
until [ "$i" -gt 3 ]; do          # lặp cho đến khi điều kiện trở thành đúng
  echo "i=$i"
  i=$((i + 1))
done                              # i=1 / i=2 / i=3
while và until khác nhau
while [ i ≤ 3 ]điều kiện đúngchạy phần thânuntil [ i > 3 ]điều kiện saichạy phần thânwhile: lặp khi còn đúnguntil: lặp tới khi đúng
while lặp phần thân chừng nào điều kiện còn đúng; until lặp cho đến khi điều kiện trở thành đúng. Cả hai đều tăng biến đếm trong phần thân để tiến dần đến lúc kết thúc.
SyntaxÝ nghĩaExample
while [ cond ]; do … donelặp chừng nào điều kiện còn đúngwhile [ "$i" -lt 3 ]; do …; done
until [ cond ]; do … donelặp cho đến khi điều kiện trở thành đúnguntil [ -f done.flag ]; do …; done

Viết một script thử lại (retry) lặp lại công việc trong khi đếm số vòng.

① Mở retry.sh bằng vi retry.sh, nhấn i để vào insert mode, và viết #!/bin/sh ở dòng đầu tiên.

② Thiết lập một biến đếm, lặp bằng while đến một giới hạn trong khi in ra số lần thử, và tăng biến đếm bên trong phần thân.

③ Xác nhận rằng viết lại cùng công việc bằng until [ "$i" -gt "$max" ] cho cùng kết quả.

④ Nhấn Esc, lưu bằng :wq, rồi thêm quyền thực thi.

⑤ Chạy script và xác nhận nó lặp đúng số lần đã đặt.

⑥ Nếu bạn chưa chắc nên viết gì, hãy sao chép nội dung trong bảng đáp án rồi dán vào insert mode của vi.

Linux console
0 / 3 đã hoàn thành
Loading Linux Terminal...

Điều khiển vòng lặp for — break / continue

Ngay cả khi đang giữa chừng một vòng lặp for, bạn vẫn có thể đổi luồng bằng breakcontinue.

continue bỏ qua phần còn lại của vòng đó và chuyển sang phần tử kế tiếp, còn break kết thúc chính vòng lặp.

Kết hợp chúng với một điều kiện như if [ điều kiện ]; then continue; fi hoặc if [ điều kiện ]; then break; fi để bỏ qua phần tử bạn không cần hoặc dừng lại khi đã đủ.

for n in 1 2 3 4 5; do
  if [ "$n" -eq 3 ]; then continue; fi  # bỏ qua 3
  if [ "$n" -eq 5 ]; then break; fi     # thoát ra tại 5
  echo "n=$n"
done                                    # n=1 / n=2 / n=4
Luồng break / continue trong for
n=1chạy phần thânin n=1n=2chạy phần thânin n=2n=3continuebỏ phần còn lạin=4chạy phần thânin n=4n=5breakkết thúc vòng lặpsang phần tử kếcontinue: bỏ qua vòng nàybreak: thoát vòng lặp
for chạy phần thân lần lượt từ n=1. Tại n=3, continue bỏ qua phần còn lại và chuyển sang phần tử kế, và tại n=5, break kết thúc chính vòng lặp (đầu ra là n=1 / n=2 / n=4).
SyntaxÝ nghĩaExample
continuebỏ qua vòng này và sang vòng kếif [ -z "$x" ]; then continue; fi
breakthoát khỏi vòng lặp giữa chừngif [ "$n" -gt 100 ]; then break; fi

Viết một script tổng hợp bỏ qua dòng rỗng và dừng tại một giới hạn.

① Mở collect.sh bằng vi collect.sh, nhấn i để vào insert mode, và viết #!/bin/sh ở dòng đầu tiên.

② Lặp một danh sách giá trị bằng for, bỏ qua các giá trị rỗng hoặc không mong muốn bằng continue, và thoát vòng lặp bằng break khi đạt giới hạn.

③ Nhấn Esc, lưu bằng :wq, rồi thêm quyền thực thi.

④ Chạy script và xác nhận các giá trị đã bỏ qua cùng vị trí mà nó dừng lại.

⑤ Nếu bạn chưa chắc nên viết gì, hãy sao chép nội dung trong bảng đáp án rồi dán vào insert mode của vi.

Linux console
0 / 3 đã hoàn thành
Loading Linux Terminal...

Điều khiển vòng lặp while — break / continue

Ngoài việc kiểm tra điều kiện trong while, dùng breakcontinue cho phép bạn dừng sớm hoặc bỏ qua một vòng.

continue bỏ qua vòng đó và quay lại kiểm tra điều kiện, còn break thoát khỏi vòng lặp mà không chờ điều kiện.

Lưu ý ở đây: nếu bạn không đặt việc cập nhật biến đếm ở đầu phần thân (trước continue), thì vòng bị bỏ qua sẽ không cập nhật nó và vòng lặp không bao giờ kết thúc.

i=0
while [ "$i" -lt 10 ]; do
  i=$((i + 1))                          # tăng ở đầu
  if [ "$i" -eq 3 ]; then continue; fi  # bỏ qua vòng thứ 3
  if [ "$i" -eq 6 ]; then break; fi     # thoát ra ở vòng thứ 6
  echo "attempt $i"
done                                    # attempt 1 / 2 / 4 / 5
Luồng break / continue trong while
i=1chạy phần thânattempt 1i=2chạy phần thânattempt 2i=3continuequay lại kiểm trai=4chạy phần thânattempt 4i=5chạy phần thânattempt 5i=6breakkết thúc vòng lặpsang vòng kếcontinue: quay lại kiểm trabreak: thoát vòng lặp
while chạy phần thân chừng nào điều kiện còn đúng, tăng i thêm 1 mỗi lần. Tại i=3, continue quay lại kiểm tra điều kiện, và tại i=6, break kết thúc vòng lặp mà không chờ điều kiện (đầu ra là attempt 1 / 2 / 4 / 5).
SyntaxÝ nghĩaExample
continuebỏ qua vòng này, quay lại kiểm traif [ $((i % 3)) -eq 0 ]; then continue; fi
breakthoát vòng lặp mà không chờ điều kiệnif [ "$found" -ge 4 ]; then break; fi
vị trí cập nhật biến đếmcập nhật nó trước continueđặt i=$((i + 1)) ở đầu phần thân

Viết một script quét lặp bằng while, bỏ qua các vòng không cần, và dừng khi đã có đủ số lượng cần.

① Mở scan.sh bằng vi scan.sh, nhấn i để vào insert mode, và viết #!/bin/sh ở dòng đầu tiên.

② Thiết lập một biến đếm, lặp bằng while đến một giới hạn, và tăng biến đếm thêm 1 ở đầu phần thân.

③ Bỏ qua các vòng thỏa một điều kiện nào đó bằng continue, và thoát vòng lặp bằng break khi đạt số lượng cần.

④ Nhấn Esc, lưu bằng :wq, rồi thêm quyền thực thi.

⑤ Chạy script và xác nhận các vòng đã bỏ qua cùng vị trí mà nó dừng lại.

⑥ Nếu bạn chưa chắc nên viết gì, hãy sao chép nội dung trong bảng đáp án rồi dán vào insert mode của vi.

Linux console
0 / 3 đã hoàn thành
Loading Linux Terminal...
QUIZ

Kiểm tra kiến thức

Hãy trả lời từng câu hỏi một.

Câu 1for f in *.txt; do ... done lặp qua cái gì?

Câu 2Từ khóa nào lặp chừng nào điều kiện còn đúng?

Câu 3Cái nào chỉ bỏ qua vòng đó và chuyển sang vòng kế tiếp?