Câu hỏi của tôi là về ưu tiên chuyển hướng là bash. Giả sử bạn có một lệnh:
cmd1 < cmd2 > cmd3
Nó sẽ dịch sang:
(cmd1 < cmd2) > cmd3
Hoặc là
cmd1 < (cmd2 > cmd3)
Câu hỏi của tôi là về ưu tiên chuyển hướng là bash. Giả sử bạn có một lệnh:
cmd1 < cmd2 > cmd3
Nó sẽ dịch sang:
(cmd1 < cmd2) > cmd3
Hoặc là
cmd1 < (cmd2 > cmd3)
Câu trả lời:
Các quy định cụ thể tiêu chuẩn POSIX rằng chuyển hướng vỏ được từ trái sang phải; đó là, trật tự là rất quan trọng:
Cấu trúc
2>&1
thường được sử dụng để chuyển hướng lỗi tiêu chuẩn sang cùng một tệp với đầu ra tiêu chuẩn. Vì các chuyển hướng diễn ra từ đầu đến cuối, thứ tự chuyển hướng là rất quan trọng. Ví dụ:ls > foo 2>&1
chỉ đạo cả đầu ra tiêu chuẩn và lỗi tiêu chuẩn vào tập tin
foo
. Tuy nhiên:ls 2>&1 > foo
chỉ hướng đầu ra tiêu chuẩn vào tập tin
foo
vì lỗi tiêu chuẩn được nhân đôi thành đầu ra tiêu chuẩn trước khi đầu ra tiêu chuẩn được chuyển đến tập tinfoo
.
bash
hoạt động tuân thủ phần này của tiêu chuẩn:
$ ls doesnotexist > foo 2>&1
$ cat foo
ls: cannot access doesnotexist: No such file or directory
$ ls doesnotexist 2>&1 > foo
ls: cannot access doesnotexist: No such file or directory
$ cat foo
$
Đối với đường ống:
Bởi vì việc gán đường ống của đầu vào tiêu chuẩn hoặc đầu ra tiêu chuẩn hoặc cả hai diễn ra trước khi chuyển hướng, nó có thể được sửa đổi bằng cách chuyển hướng. Ví dụ:
$ command1 2>&1 | command2
gửi cả đầu ra tiêu chuẩn và lỗi
command1
tiêu chuẩn của đầu vào tiêu chuẩn củacommand2
.
ls > foo 2>&1
có nghĩa là chuyển hướng thiết bị xuất chuẩn sang foo sau đó chuyển hướng thiết bị xuất chuẩn sang thiết bị xuất chuẩn. Vì vậy, điều này không nên làm việc. Tương tự lệnh thứ hai sẽ hoạt động. Tôi đang thiếu gì ở đây?
bash
nói chung là tuân thủ POSIX, ngoại trừ trong các tình huống được nêu ở đây , nơi bash
hành vi mặc định khác nhau. Để làm cho bash
phù hợp hơn, bạn có thể sử dụng --posix
tùy chọn.
ls > foo 2>&1
, hoạt động như thế này: đầu tiên, đầu ra tiêu chuẩn được chuyển hướng đến foo
, sau đó, lỗi tiêu chuẩn được chuyển hướng đến đầu ra tiêu chuẩn, hiện là tệp foo
. Ví dụ thứ hai ls 2>&1 > foo
, hoạt động như thế này: lỗi tiêu chuẩn được chuyển hướng đến đầu ra tiêu chuẩn trước khi đầu ra tiêu chuẩn được chuyển hướng đến foo
, do đó, lỗi tiêu chuẩn được lặp lại cục bộ thay vì được dẫn đến tệp.
ls 2>&1 >foo
có lẽ bạn có thể nghĩ về nó như thế này. stderr từ 'ls' được chuyển hướng đến thiết bị xuất chuẩn. Điều này sẽ xảy ra! Nó sẽ đi đến nơi mà thiết bị xuất chuẩn hiện đang được chỉ định để đi, bất kể bất kỳ chỉ thị nào khác liên quan đến thiết bị xuất chuẩn .. (vì đây là chỉ thị chính / đầu tiên của nó ) .. Sau đó, đến một chỉ thị khác nói rằng thiết bị xuất chuẩn sẽ chuyển đến "foo", và nó ... Hãy nhớ rằng: stderr không được chuyển thành thực sự trở thành thiết bị xuất chuẩn .. Nó chỉ đi đến nơi thiết bị xuất chuẩn được chỉ định tại thời điểm chỉ thị. (ví dụ: thiết bị đầu cuối)
Tôi đoán cũng không. Một cặp dấu ngoặc có nghĩa là một vỏ phụ. Nhưng trong trường hợp này, không có vỏ phụ sẽ được bắt đầu vì chuyển hướng. Bash chỉ đơn giản là ăn cmd2
vào stdin và ăn stdout vào cmd3
.
Tôi đang suy nghĩ, bạn có ý gì đó như thế cmd1 | cmd2 | cmd3
nào? Bởi vì cmd2
và cmd3
thường là các tệp bình thường thay vì "cmds".