Chạy một lệnh trên nhiều tệp


19

Tôi đã có một thư mục chứa nhiều tệp (xyz1, xyz2, cho đến xyz5025) và tôi cần chạy một tập lệnh trên mỗi tệp, lấy xyz1.faa, xyz2.faa, v.v.

Lệnh cho một tệp duy nhất là:

./transeq xyz1 xyz1.faa -table 11

Có cách nào để làm điều đó tự động? Có lẽ là một kết hợp để làm?

Câu trả lời:


32
for file in xyz*
do
  ./transeq "$file" "${file}.faa" -table 11
done

Đây là một forvòng lặp đơn giản sẽ lặp lại trên mọi tệp bắt đầu xyztrong thư mục hiện tại và gọi ./transeqchương trình với tên tệp là đối số đầu tiên, tên tệp theo sau là ".faa" làm đối số thứ hai, theo sau là "-table 11" .


4
Hoặc, như một lớp lót : for file in xyz*; do ./transeq "$file" "${file}.faa" -table 11; done. Tôi gõ loại này mọi lúc. Và nếu bạn muốn xác minh rằng tên tệp, v.v. đang được mở rộng theo cách bạn muốn, chỉ cần đặt echoquyền sau dolần đầu tiên, sau đó quay lại lịch sử shell của bạn và xóa nó lần thứ hai.
Dave Tweed

"$file".faadễ dàng hơn một chút để nhập như một phần của một lớp lót tương tác và an toàn vì .faakhông chứa bất kỳ siêu ký tự vỏ nào cần được trích dẫn.
Peter Cordes

2
Lưu ý, nếu bạn kết thúc với một phần chạy và muốn khởi động lại vòng lặp, toàn xyz*cầu cũng sẽ nhận các tệp .faa. Đối với bash, hãy chạy shopt -s extglob( tham chiếu ), sau đó sử dụng for file in xyz!(*.faa) ...để loại trừ các tệp .faa khỏi được gửi qua vòng lặp.
Jeff Schaller

24

Nếu bạn cài đặt GNU Parallel, bạn có thể thực hiện song song như thế này:

parallel ./transeq {} {}.faa -table 11 ::: xyz*

Nếu chương trình của bạn sử dụng nhiều CPU, nó sẽ tăng tốc khá nhanh.


6

Bạn có thể làm một cái gì đó như thế này trên một bashdòng lệnh:

printf '%s\n' {1..5025} | xargs -l -I {} -t ./transeq xyz{} xyz{}.faa -table 11

Chúng tôi đang tạo các số nguyên từ 1 đến 5025, một / dòng, sau đó cung cấp từng số một cho xargs, đóng gói số nguyên vào {}và sau đó ghép nó vào dòng lệnh ./transeq theo cách thích hợp.

Nếu bạn không có tiện ích mở rộng cú đúp {n..m}thì bạn có thể gọi seqtiện ích để tạo các số đó.

Hoặc, bạn luôn có thể mô phỏng thế hệ số thông qua:

yes | sed -n =\;5025q | xargs ...

1
Đó là cách quá phức tạp. for i in {1..5025}; do ./transeq "xyz$i" "xyz$i".faa -table 11; donelà cách dễ dàng hơn để suy nghĩ và loại. Nếu bạn muốn nó in lệnh trước khi thực hiện chúng, hãy sử dụng set -x.
Peter Cordes

Vâng, điều đó đúng, nhưng cách OP đặt ra câu hỏi đối với tôi dường như chỉ các tệp có tên xyz1 .. xyz5025 mới được quan tâm. Vì vậy, tôi nghĩ rằng nếu chúng ta làm điều đó bằng cách sử dụng cho xyz * thì chúng ta cần một cách để từ chối các tệp không tuân thủ ... do đó, điều này. Lý tưởng nhất là nếu OP muốn tất cả các tệp trong một thư mục được xử lý, vậy thì tại sao lại đưa từ 1 lên 5025? Chỉ cần nói rằng tôi muốn tất cả các tệp được xử lý theo cách quy định sẽ là đủ.

1
Nhìn vào vòng lặp tôi đã viết. Nó sử dụng for i in {1..5025}để đạt được kết quả chính xác như của bạn. Bạn cũng có thể viết for ((i=1 ; i<=5025 ; i++)); do ./transeq "xyz$i" "xyz$i".faa -table 11; donebằng bash, nhưng tôi thường sử dụng {a..b}cú pháp phạm vi vì nó nhanh hơn để gõ.
Peter Cordes

4

Sử dụng find, hữu ích khi các tệp của bạn nằm rải rác trong các thư mục

find -name "xyz*" -exec ./transeq {} {}.faa -table 11 \;

4

Giả sử bạn có nhiều hơn một lõi và mỗi lệnh gọi có thể chạy độc lập với phần còn lại, bạn sẽ đạt được tốc độ khá nhanh với các lần chạy song song.

Một cách tương đối đơn giản để thực hiện việc này là thông qua -Ptham số của xargs- ví dụ: nếu bạn có 4 lõi:

echo xyz{1..5025} | \
    xargs -n 1 -P 4 -I{} /path/to/transeq xyz{} xyz{}.faa -table 11

Các -n 1kể xargsđể chọn chỉ có một lập luận ra khỏi danh sách cho mỗi lời gọi (theo mặc định nó sẽ vượt qua rất nhiều) , và -P 4nói với nó để đẻ trứng 4 quy trình cùng lúc - khi một chết, một cái mới được sinh ra.

IMHO, bạn không cần phải cài đặt song song GNU cho trường hợp đơn giản này - xargsđủ.


0

Bạn có thể dùng xarg

ls | xargs -L 1 -d '\n' your-desired-command

-L 1 gây ra 1 mục tại một thời điểm

-d '\n'làm cho đầu ra của lsđược phân chia dựa trên dòng mới.

Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.