This page is READ-ONLY. It is generated from the old site.
All timestamps are relative to 2013 (when this page is generated).
If you are looking for TeX support, please go to VietTUG.org

What is pipe in Linux ?

vẫn còn nhu cầu tuyển người đi uống cafe.
Added by bronzeboyvn about 3 years ago  »  Votes: 1/1

Tôi viết một đoạn script thế này

 1 #!/bin/bash
 2 
 3 max=-1
 4 
 5 ls -lo | awk '{print $4}' |
 6 while read size
 7 do
 8     if [ "$size" -gt "$max" ]
 9     then
10         max=$size
11     fi
12 done
13 
14 echo "max size of file in current directory $max" 

Mục đích rất rõ ràng, tôi muốn in ra dung lượng của file lớn nhất trong thư mục hiện hành. Kết quả đoạn script trên cho $max bằng -1. Đây không phải là kết quả tôi mong đợi.

Lỗi lầm đã mắc ở đâu? (hướng dẫn: xem định nghĩa pipe)

Đưa ra giải pháp của bạn (chỉ cần 1 giải pháp)

Trả lời đúng 2 câu trên, tôi mời bạn cuối tuần một chầu cafe. Còn chờ gì nữa!


Comments

Added by about 3 years ago

Bài này hay quá. Mình không đạt giải cà phê được rồi :)

Added by about 3 years ago

1. Cái này trả lời bên FB rồi giờ vào trả lời lại :) Với định nghĩa của pipelines trong ngữ cảnh Shell Command Language trong Posix standard thì đoạn code chẳng có cái gì sai cả :)), (bash cũng định nghĩa pipeline giống vậy!) và đoạn code trên chạy ngon lành với zsh, ksh, ... nhưng không chạy với bash, lý do là bash chạy từng command của pileline trong một subshell riêng biệt và từ root env thì không thể truy cập vào cái biến của subshell.

2. Giải pháp thì đơn giản là đem cái echo vào trong subshell. Chỉ cần nhóm while và echo vào chung một compound command bằng cách sử dụng { }:

 1 #!/bin/bash
 2 
 3 max=-1
 4 
 5 ls -lo | awk '{print $4}' | {
 6 while read size
 7 do
 8     if [ "$size" -gt "$max" ]
 9     then
10         max=$size
11     fi
12 done
13 
14 echo "max size of file in current directory $max" 
15 }

Giải pháp 2: Đem while ra ngoài root env, gắn stdin của while với stdout của pipe thông qua redirection:

 1 #!/bin/bash
 2 
 3 max=-1
 4 
 5 while read size
 6 do
 7     if [ "$size" -gt "$max" ]
 8     then
 9         max=$size
10     fi
11 done< <(ls -lo | awk '{print $4}')
12 
13 echo "max size of file in current directory $max" 

Giải pháp 3: dùng zsh, ksh :))

Added by about 3 years ago

Bác CT lại ... mất một chầu cà phê rất là đắt nữa đây hehe :)

Added by bronzeboyvn about 3 years ago

Một vé đi cafe dành cho tuanndh, hy vọng sáng thứ 7 hoặc sáng chủ nhật tuanndh sắp xếp được thời gian. tuanndh cứ liên lạc ở đây ( có thể liên lạc cá nhân, xem Cách che nội dung bài viết).

Trường hợp dùng zsh, ksh shell làm tôi bất ngờ, vì nằm ngoài đáp án mà tôi biết. Nói về bash script thì có thể giải thích thế này:

<statement 1> | <statement 2> | <statement 3>

Mỗi lần dùng 1 pipe, một process con được tạo ra để nhận output của statement bên trái pipe, đem về làm input cho mình (statement bên phải pipe). Cụ thể ở đây, sẽ có 2 processes. Để tiện theo dõi, ta chèn trong vòng lặp while ở statement 3 sleep 2. Giả sử script của ta tên whatpipe.sh, chạy nó ở 1 tab, mở 1 tab khác chạy ps -af. Ta thấy có 2 processes tên whatpipe.sh và 1 process tên sleep. Xem process ID và parent process ID, thấy rõ chúng có quan hệ "ông-cha-con".

Quay lại script bị lỗi, ta có max trong process ông, và max trong process cháu. Khi in max là in cái của process ông, rõ ràng nó vẫn là -1.

Added by about 3 years ago

{{{allow z,bronzeboyvn}}}

Hi CT, vì một lỗi logic khi phát triển tính năng #617 mà tự nhiên mình có quyền sửa các bài bình luận ở đây. Do đó, mình đã chỉ một số bài cho dễ nhìn hơn. Tuy nhiên, theo thiết kế thì mình không được phép sửa (với quyền Blogger thì mình chỉ sửa được bài của chính mình mà thôi.)

Xin lỗi CT vì sự cố này nhé. Cảm ơn CT.

PS: Tính năng tô màu cho tập tin .bash (#628) cũng đã được thêm. Mình phải viết lại nên một số chỗ vẫn chưa vừa ý. Enjoy!

Added by about 3 years ago

Cái pipe bạn nói là hiểu theo lập trình C về hệ thống Unix. Còn trong ngữ cảnh của Shell Command Language thì không phải thế. Posix, Bash đều định nghĩa các thành phần của pipe là một command (max = $size cũng là một command và phải chạy đúng), không có quy định nào về implemention nó thành một subshell cả. Đây là một trường hợp bash không đạt chuẩn Posix! Tuy nhiên theo mình thì việc bash implement thành các subshell cũng chấp nhận được vì khi làm việc với pipe thường dựa trên nguyên tắc blackbox, mà dùng subshell thì còn không bị side-effect đúng style đang hot nữa chứ ;-)

Cafe thì để khi khác :-)

Added by about 3 years ago

Khi làm việc với Linux thì đập ngay vào mặt là Bash. Giờ mình mới thấy tiếc :))

Added by bronzeboyvn about 3 years ago

Cám ơn vanchutr đã cung cấp thêm 1 giải pháp. Mình dời comment của vanchutr ngoài mục Tin tức vào đây:

 1 #!/bin/bash
 2 
 3 max=-1
 4 
 5 ls -lo | awk '{print $4}' | sed '1d' > /tmp/info.txt
 6 for i in `cat /tmp/info.txt`
 7 do
 8      if [ $i  -gt $max ]
 9      then
10          echo $i
11          max=$i 
12      fi
13 done
14 
15 echo "max size of file in current directory $max"