Di chuyển hàng triệu tệp đến một thư mục khác với các mẫu tên cụ thể


10

Tôi có hàng triệu tệp với danh pháp sau trên máy Linux:

1559704165_a1ac6f55fef555ee.jpg

10 chữ số đầu tiên là dấu thời gian và những chữ số theo sau là một _id cụ thể. Tôi muốn di chuyển tất cả các tệp khớp với id tên tệp cụ thể sang một thư mục khác.

Tôi đã thử điều này trên thư mục với các tập tin

find . -maxdepth 1 -type f | ??????????_a1ac*.jpg |xargs mv -t "/home/ubuntu/ntest"

Tuy nhiên tôi nhận được một lỗi cho biết:

bash 1559704165_a1ac6f55fef555ee.jpg: command not found

Khi tôi thử, mv ??????????_a1ac*.jpg tôi nhận được danh sách đối số lỗi quá dài. Tôi có ít nhất 15 mẫu tên tệp khác nhau. Làm thế nào để tôi di chuyển chúng.


1
Bash nói lên tất cả: nó cố gắng thực hiện tên tệp đó vì đây là lần đầu tiên trên dòng trong giai đoạn 2 của ống (ống thứ hai của bạn là | ??????????_a1ac*.jpg:: bash mở rộng nó thành một số tên tệp, lần đầu tiên 1559704165_a1ac6f55fef555ee.jpg, bạn kết thúc , trong giai đoạn ống thứ 2 đó, cố gắng thực hiện : 1559704165_a1ac6f55fef555ee.jpg next_matching_filename 3rd_matching_filename ... nth_matching_filename. Tôi đoán thay vào đó bạn đã cố gắng lọc tên tệp đó (xem câu trả lời bên dưới cho điều đó)
Olivier Dulac

Câu trả lời:


15

Bạn nên sử dụng:

find . -maxdepth 1 -type f -name '??????????_a1ac*.jpg' \
-exec mv -t destination "{}" +

Vì vậy, maxdepth 1có nghĩa là bạn muốn tìm kiếm trong thư mục hiện tại không có thư mục con.

type f có nghĩa là chỉ tìm tập tin.

name '??????????_a1ac*.jpg' là một mẫu phù hợp với tập tin bạn đang tìm kiếm.

mv -t destination "{}" +có nghĩa là di chuyển các tập tin phù hợp đến đích. Ở đây +thêm các tệp phù hợp mới vào tệp trước đó như:

mv -t dest a b c d

Ở đây abcd là các tập tin khác nhau.


Cảm ơn đã trả lời chính xác câu hỏi của người này. Thay vì chỉ đơn giản là từ chối một giải pháp, có lẽ bạn có thể giải thích làm thế nào / cái gì / tại sao. Thay vì hữu ích cho một người, một lần, nó có thể hữu ích cho mọi người, mọi lúc. Câu hỏi tương tự đã được hỏi và trả lời vô số lần trong 40-50 năm qua. Vấn đề là, nó không bao giờ giải thích tốt. Dạy một người đàn ông để cá .. Trong khi đó: gnu.org/software/findutils/manual/html_node/find_html/... và như thường là trường hợp của Wikipedia có ích hơn các tài liệu chính thức: en.wikipedia.org/wiki/Find_ ( Unix)
lên tiếng

Xem câu trả lời cập nhật.
Prvt_Yadav

Lưu ý rằng đó -tlà một phần mở rộng GNU và do đó có thể không có sẵn trên các loại dẫn xuất UNIX khác.
Kevin

Khi bạn nói "Dấu ngoặc kép ngăn chia tách từ." Tôi đoán bạn đang đề cập đến "{}", trong trường hợp đó tôi muốn chỉ ra rằng {}nó không được mở rộng bởi trình bao và không cần phải trích dẫn. Shell chuyển qua {}để tìm, và tìm thấy {}và thay thế nó bằng tên đường dẫn. Find exec không sử dụng trình phân tích cú pháp shell và không thực hiện bất kỳ phân tách từ nào. Trích dẫn nó không làm hại gì cả, chỉ là sự biện minh được đưa ra là một chút không chính xác.
jw013

@ jw013 cảm ơn.
Prvt_Yadav

11

Lệnh của bạn,

find . -maxdepth 1 -type f | ??????????_a1ac*.jpg |xargs mv -t "/home/ubuntu/ntest"

Đặt danh sách tất cả các tệp ĐẾN tất cả các tệp!

find . -maxdepth 1 -type f -name `*_a1ac*.jpg` -print0 |\
xargs  -0 -r mv -t "/home/ubuntu/ntest"

sẽ thực hiện các mẹo.


1
cảm ơn rất nhiều ... giải pháp của bạn cũng có hiệu quả ... cảm ơn bạn đã cho tôi biết tôi đã sai ở đâu
Apricot

8

Bạn đang rất thân thiết. Bạn nên sử dụng -nametùy chọn để find. Và nhớ trích dẫn mẫu.

Vì thế

find . -maxdepth 1 -type f -name '??????????_a1ac*.jpg' |xargs mv -t "/home/ubuntu/ntest"

Rất cám ơn ... giải pháp của bạn cũng có hiệu quả .... cảm ơn thêm vì đã cho tôi biết tôi đã gần với giải pháp .... đó là động lực cho một người mới như tôi
Apricot

1
bạn nên thêm một -print0đối số cuối cùng vào tìm kiếm (thay vì mặc định: -print) và thêm một -0tùy chọn đầu tiên vào xargs (tức là xargs -0 mv -t "/home/ubuntu/ntest":). bằng cách đó, tất cả các loại tên tệp kỳ lạ (có khoảng trắng trong đó, với "dòng mới" trong đó, v.v.) có thể được xử lý. find . -maxdepth 1 -type f -name '??????????_a1ac*.jpg' -print0 |xargs -0 mv -t "/home/ubuntu/ntest" (chỉ hoạt động với tìm kiếm giống như GNU)
Olivier Dulac

2

Không phải là "tốt" như các findgiải pháp, nhưng một giải pháp hợp lệ khác là làm cho các mvlệnh trở nên chi tiết hơn.

Điều này thực hiện 4096 di chuyển, với số lượng tệp được di chuyển ít hơn trên mỗi mvthao tác.

FILEPAT=a1ac
for i in $(seq $((0x000)) $((0xfff))); 
do 
   H=$(printf '%x\n' $i)
   mv 1559704165_${FILEPAT}${H}*.jpg /home/ubuntu/ntest
done

Đây là một hack thông minh cho những người không có find(vì lý do gì).
rừng

-1

Nếu bạn muốn di chuyển các tệp trên cùng một hệ thống máy chủ, mà tôi đoán bạn đang làm với máy của mình mv, rsynccó thể là một tùy chọn nhanh hơn:

rsync -av --inplace -W /source/??????????_a1ac*.jpg /home/ubuntu/ntest/

--inplace-Wđược thiết lập để tăng tốc quá trình.

Nếu điều này mang lại một danh sách đối số lỗi quá dài thì bạn có thể cung cấp danh sách chorsync

Tạo danh sách với find, ví dụ

find . -maxdepth 1 -type f -name '??????????_a1ac*.jpg' > /tmp/my_image_list.txt

và đưa nó cho rsync

rsync -av --inplace -W --files-from=/tmp/my_image_list.txt /path/to/files /home/ubuntu/ntest/

Nguồn ở đây là /path/to/filesbởi vì rsyncsẽ coi danh sách bạn cung cấp có liên quan đến nguồn của bạn.


Vấn đề là: rsyncnhanh hơn mv, nếu các tệp không nằm trên cùng một hệ thống tệp .


Điều này có khả năng gặp phải lỗi "danh sách đối số quá dài" mà OP đã đề cập
Grump

@Grump, để tránh điều này, OP có thể viết danh sách các tệp cần sao chép vào một tệp, tức là find . -maxdepth 1 -type f -name '??????????_a1ac*.jpg' > /tmp/my_image_list.txtsau đó chuyển nó sang rsync --files-from=/tmp/my_image_list.txt. Vấn đề rsynclà nhanh hơn. Trừ khi các tệp nằm trên cùng một hệ thống tệp, mà OP không được chỉ định.
Robert Riedl

@RobertRiedl: bạn nên chỉnh sửa câu trả lời của mình và thêm thông tin này. Bình luận có thể là vô thường.
NickD

@NickD, tôi đã cập nhật câu trả lời của mình.
Robert Riedl
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.