Trước hết, không sử dụng ls
đầu ra như một danh sách tập tin . Sử dụng mở rộng vỏ hoặc find
. Xem dưới đây để biết hậu quả tiềm năng của ls + xargs lạm dụng và ví dụ về hợp xargs
sử dụng.
1. Cách đơn giản: cho vòng lặp
Nếu bạn muốn xử lý chỉ các tệp bên dưới A/
, thì một for
vòng lặp đơn giản là đủ:
for file in A/*.dat; do ./a.out < "$file" > "${file%.dat}.ans"; done
2. pre1 Tại sao không ls | xargs
?
Dưới đây là một ví dụ về cách điều xấu có thể bật nếu bạn sử dụng ls
với xargs
cho công việc. Hãy xem xét một kịch bản sau đây:
đầu tiên, hãy tạo một số tệp trống:
$ touch A/mypreciousfile.dat\ with\ junk\ at\ the\ end.dat
$ touch A/mypreciousfile.dat
$ touch A/mypreciousfile.dat.ans
xem các tập tin và chúng không chứa gì:
$ ls -1 A/
mypreciousfile.dat
mypreciousfile.dat with junk at the end.dat
mypreciousfile.dat.ans
$ cat A/*
chạy một lệnh ma thuật bằng cách sử dụng xargs
:
$ ls A/*.dat | xargs -I file sh -c "echo TRICKED > file.ans"
kết quả:
$ cat A/mypreciousfile.dat
TRICKED with junk at the end.dat.ans
$ cat A/mypreciousfile.dat.ans
TRICKED
Vì vậy, bạn chỉ cần ghi đè lên cả hai mypreciousfile.dat
và mypreciousfile.dat.ans
. Nếu có bất kỳ nội dung nào trong các tệp đó, nó sẽ bị xóa.
2. Sử dụng xargs
: cách thích hợp với find
Nếu bạn muốn nhấn mạnh vào việc sử dụng xargs
, hãy sử dụng -0
(tên kết thúc null):
find A/ -name "*.dat" -type f -print0 | xargs -0 -I file sh -c './a.out < "file" > "file.ans"'
Lưu ý hai điều:
- bằng cách này, bạn sẽ tạo các tệp có
.dat.ans
kết thúc;
- điều này sẽ phá vỡ nếu một số tên tệp chứa dấu ngoặc kép (
"
).
Cả hai vấn đề có thể được giải quyết bằng cách gọi shell khác nhau:
find A/ -name "*.dat" -type f -print0 | xargs -0 -L 1 bash -c './a.out < "$0" > "${0%dat}ans"'
3. Tất cả được thực hiện trong find ... -exec
find A/ -name "*.dat" -type f -exec sh -c './a.out < "{}" > "{}.ans"' \;
Điều này, một lần nữa, tạo ra .dat.ans
các tệp và sẽ phá vỡ nếu tên tệp chứa "
. Để thực hiện điều đó, hãy sử dụng bash
và thay đổi cách nó được gọi:
find A/ -name "*.dat" -type f -exec bash -c './a.out < "$0" > "${0%dat}ans"' {} \;