2011-10-13 17 views
5

Làm cách nào để lặp lại tất cả các dòng đầu ra bằng lệnh bằng cách sử dụng zsh, mà không cần thiết lập IFS?Làm cách nào để lặp lại tất cả các dòng đầu ra bằng một lệnh trong zsh?

Lý do là tôi muốn chạy lệnh chống lại mọi đầu ra tệp bằng lệnh và một số tệp này chứa dấu cách.

Ví dụ, với các tập tin bị xóa:

foo/bar baz/gamma 

Nghĩa là, một thư mục duy nhất 'foo', có chứa một thư mục phụ 'bar baz', có chứa một tập tin 'gamma.

Sau đó chạy:

git ls-files --deleted | xargs ls 

sẽ báo cáo trong đó tập tin được xử lý như hai tập tin: 'foo/bar', và '/ baz/gamma.

Tôi cần nó để xử lý nó như một tệp: 'foo/bar baz/gamma'.

+0

Hệ thống của bạn có lệnh xarg không? – lunixbochs

+0

@lunixboches: Có, tuy nhiên, nó vẫn không xử lý được các dòng đúng cách. – Arafangion

+2

'git ls-files -z | xargs -0 ls' sẽ sử dụng dấu phân tách rỗng (\ 0) thay vì khoảng trống – lunixbochs

Trả lời

4

Sử dụng tr-0 tùy chọn xargs, giả định rằng các dòng không chứa \000 (NUL), mà là một giả định công bằng do NUL là một trong những nhân vật mà không thể xuất hiện trong tên tập tin:

git ls-files --deleted | tr '\n' '\000' | xargs -0 ls 

này biến dòng: foo/bar baz/gamma\n vào foo/bar baz/gamma\000xargs -0 biết làm thế nào để xử lý

+0

Không thể làm tốt hơn thế, cảm ơn! (Và nó hoạt động trong bash, quá!) – Arafangion

7

Nếu bạn muốn chạy lệnh một lần cho tất cả các dòng:

01.
ls "${(@f)$(git ls-files --deleted)}" 

fparameter expansion flag có nghĩa là chia kết quả của lệnh trên dòng mới. Có một dạng tổng quát hơn (@s:||:) để phân tách tại một chuỗi tùy ý như ||. Cờ @ có nghĩa là giữ lại các bản ghi trống. Hơi gây nhầm lẫn, toàn bộ mở rộng cần phải được bên trong dấu ngoặc kép, để tránh IFS tách trên đầu ra của command substitution, nhưng nó sẽ tạo ra các từ riêng biệt cho mỗi bản ghi.

Nếu bạn muốn chạy lệnh cho mỗi dòng đến lượt mình, các thành ngữ cầm tay không phải là đặc biệt phức tạp:

git ls-filed --deleted | while IFS= read -r line; do ls $line; done 

Nếu bạn muốn chạy lệnh như vài lần như giấy phép giới hạn chiều dài dòng lệnh , sử dụng zargs.

autoload -U zargs 
zargs -- "${(@f)$(git ls-files --deleted)}" -- ls 
+0

Cảm ơn vì điều đó - có rất nhiều thông tin hữu ích ở đây nhưng tôi nghĩ xargs vẫn hiệu quả hơn vì nó sẽ chạy một lệnh cho mỗi nhóm tệp. (Điều gì sẽ xảy ra nếu tôi có quá nhiều tệp không phù hợp với danh sách arg?) – Arafangion

+0

@Arafangion 'zargs' giống như' xargs' (chạy ít nhất có thể trong khi lắp trong giới hạn độ dài dòng lệnh), chỉ với một giao diện hợp lý. – Gilles

+0

Thậm chí tốt hơn, cảm ơn. :) Sẽ kiểm tra xem nó ra. – Arafangion