2013-04-10 15 views

Trả lời

-1

Có vẻ như bạn đang tìm lệnh tìm. Tôi chưa thử nghiệm điều này, nhưng điều gì đó dọc theo các dòng sau:

files=(`find . -name *.mp3`) 
for file in "${files[@]}"; do 
    echo $file TITLE="id3info "$file" | grep '^=== TIT2' | sed -e 's/.*: //g'" ARTIST="id3info "$file" | grep '^=== TPE1' | sed -e 's/.*: //g'" 
done 

EDIT: sử dụng mảng làm cho lệnh an toàn cho các tệp có dấu cách trong tên của chúng.

+0

Điều này là hoàn toàn không an toàn và bị hỏng (bất cứ điều gì EDIT tuyên bố): nó _does_ phá vỡ với tên tập tin có chứa không gian hoặc ký tự glob. –

4

Có rất nhiều cách để làm da mèo này. Tôi sẽ sử dụng một cuộc gọi đến tìm lệnh bản thân mình:

for file in $(find . -name '*.mp3') do 
    echo $file 
    TITLE=$(id3info "$file" | grep '^=== TIT2' | sed -e 's/.*: //g') 
    ARTIST=$(id3info "$file" | grep '^=== TPE1' | sed -e 's/.*: //g') 
    echo "$ARTIST - $TITLE" 
done 

Nếu bạn có khoảng trống trong tên tập tin của bạn thì cách tốt nhất là sử dụng tùy chọn -print0 để tìm; một cách có thể là:

find . -name '*.mp3' -print0 | while read -d $'\0' file 
do 
    echo $file 
    TITLE=$(id3info "$file" | grep '^=== TIT2' | sed -e 's/.*: //g') 
    ARTIST=$(id3info "$file" | grep '^=== TPE1' | sed -e 's/.*: //g') 
    echo "$ARTIST - $TITLE" 
done 

cách khác bạn có thể lưu và khôi phục IFS. Nhờ ý kiến ​​của David W. và đặc biệt, để chỉ ra rằng phiên bản vòng while cũng có lợi ích là nó sẽ xử lý số lượng tệp rất lớn một cách chính xác, trong khi phiên bản đầu tiên mở rộng $(find) thành một vòng lặp sẽ không làm việc tại một số điểm vì mở rộng vỏ có giới hạn.

+0

Điều này không hoạt động với không gian màu trắng trong tên tệp: ( – Charlie

+0

Đúng. Có các giải pháp bằng cách thay đổi 'IFS' hoặc sử dụng' -print0'. Tôi sẽ chỉnh sửa một. – drquicksilver

+0

Điều gì sẽ xảy ra nếu tôi tìm thấy 1.000.000 tệp? shell mở rộng mệnh đề '$ (find. -name" * .mp3) 'và thay thế nó trong' for' của tôi. Không chắc rằng bộ đệm dòng lệnh của tôi là lớn, và điều xảy ra là tìm kiếm của tôi sẽ không thành công. nên rất, rất cẩn thận khi sử dụng mở rộng vỏ thành vòng lặp for –

3
find . -name \*.mp3 | (
    while read file; do 
     echo $file 
    done 
) 
+1

Khá tò mò tại sao điều này lại bị giảm giá, vì cách tiếp cận cơ bản (tìm đường ống đến vòng lặp đọc) là phản ứng nhiều hơn và đòi hỏi ít bộ nhớ hơn hầu hết các cách tiếp cận khác được đưa ra ở đây. – cdhowie

+1

bạn quên sử dụng 'IFS =' và '-r' với câu lệnh' read' của bạn, bạn không báo giá mở rộng của '$ file', bạn sử dụng một subshell vô nghĩa và không mong muốn với' (...) ', và cuối cùng, không sử dụng' -print0' với 'find' và' -d '' 'trong' read', lệnh không thành công đối với tên tệp có chứa dòng mới. Đó là rất nhiều lý do để downvote câu trả lời của bạn! PS. Tôi không phải là người đi xuống! –

+0

@cdhowie, ... và bằng cách nào đó, năm * sau * các lỗi trên đã được chỉ ra, chúng vẫn không được sửa chữa. Điều đó dường như có giá trị một downvote (mà tôi sẽ sẵn sàng đảo ngược một khi phê bình của nó không còn đúng). –

3

Điều này hoạt động với hầu hết tên tệp (bao gồm dấu cách) nhưng không phải là dòng mới, tab hoặc dấu cách kép.

find . -type f -name '*.mp3' | while read i; do 
    echo "$i" 
done 

Làm việc với tất cả tên tệp.

find . -type f -name '*.mp3' -print0 | while IFS= read -r -d '' i; do 
    echo "$i" 
done 

Nhưng nếu bạn chỉ muốn chạy một lệnh bạn có thể sử dụng xargs dụ:

find . -type f -name '*.mp3' -print0 | xargs -0 -l echo 
+0

Công việc này rất hữu ích ... Cảm ơn: D – Charlie

7

Quá nhiều những câu trả lời sử dụng mở rộng vỏ để lưu trữ các kết quả của một phát hiện. Đây không phải là điều bạn nên làm nhẹ nhàng.

Giả sử tôi có 30.000 bài hát và tiêu đề của những bài hát này trung bình khoảng 30 ký tự. Thậm chí, ngay cả bây giờ, bạn cũng không gặp phải vấn đề trắng.

Tìm kiếm của tôi sẽ trả về hơn 1.000.000 ký tự và rất có khả năng bộ đệm dòng lệnh của tôi không lớn. Nếu tôi đã làm một cái gì đó như thế này:

for file in $(find -name "*.mp3") 
do 
    echo "some sort of processing" 
done 

Vấn đề (ngoài khoảng trắng trong tên tập tin) là đệm dòng lệnh của bạn chỉ đơn giản là sẽ thả ra khỏi tràn từ find. Nó thậm chí có thể thất bại hoàn toàn âm thầm.

Đây là lý do tại sao lệnh xargs được tạo. Nó đảm bảo rằng bộ đệm dòng lệnh không bao giờ tràn.Nó sẽ thực hiện lệnh sau các xargs nhiều lần nếu cần thiết để bảo vệ đệm dòng lệnh:

$ find . -name "*.mp3" | xargs ... 

Tất nhiên, sử dụng xargs cách này vẫn sẽ nghẹt thở trên không gian màu trắng, nhưng việc triển khai hiện đại của xargsfind có một cách xử lý vấn đề này:

$ find . -name "*.mp3 -print0 | xargs --null ... 

Nếu bạn có thể đảm bảo rằng tên tập tin sẽ không có các tab hoặc \n (hoặc không gian kép) trong đó, đường ống một tìm vào một vòng lặp while là tốt hơn:

find . -name "*.mp3" | while read file 
do 

Đường ống sẽ gửi tệp đến while read trước khi bộ đệm dòng lệnh đầy. Thậm chí tốt hơn, các read file đọc trong một dòng toàn bộ và sẽ đặt tất cả các mặt hàng được tìm thấy trong dòng đó vào $file. Nó không hoàn hảo bởi vì read vẫn bị ngắt trên khoảng trắng nên các tên tệp như:

I will be in \n your heart in two lines.mp3 
I love song names with  multiple spaces.mp3 
I \t have \t a \t thing \t for \t tabs.mp3. 

Vẫn thất bại. Biến $file aill nhìn thấy chúng như:

I will be in 
your heart in two lines.mp3 
I love song names with multiple spaces.mp3 
I have a thing for tabs.mp3. 

Để có được xung quanh vấn đề này , bạn phải sử dụng find ... -print0 sử dụng null như chia đầu vào. Sau đó, hoặc thay đổi IFS để sử dụng giá trị rỗng hoặc sử dụng tham số -d\0 trong khi đọc câu lệnh trong BASH shell.

+2

+1. Nên có một dấu hiệu lớn 'ĐỌC NÀY TRƯỚC KHI BẠN PROCEED' trong trường hợp ai đó nhập đoạn mã cố gắng phân tích cú pháp 'ls' trỏ đến các câu hỏi được trả lời đúng. Có vẻ như số lượng câu hỏi với loại vấn đề này quá lớn đến nỗi nó thực sự sẽ tiết kiệm cả OP cũng như các linh hồn hữu ích ở đây rất nhiều thời gian. Và đưa ra số lượng _wrong_ câu trả lời cho loại vấn đề ở đây, oh boy ... –

4
find . -name *.mp3 -exec echo {} \; 

Chuỗi {} được thay thế bằng tên tập tin hiện đang được xử lý ở khắp mọi nơi nó xảy ra trong các đối số cho lệnh, không chỉ trong lý luận mà nó là một mình, như trong một số phiên bản của find.

Vui lòng kiểm tra người đàn ông tìm kiếm để biết thêm thông tin http://unixhelp.ed.ac.uk/CGI/man-cgi?find

Các vấn đề liên quan