Linux (mv hoặc cp) tệp cụ thể từ danh sách văn bản của tệp?


34

Tôi có một thư mục gồm nhiều tệp, khoảng 50.000 tệp và các tệp khác trên máy chủ. Tôi cần chuyển những cái cụ thể sang thư mục khác. Tôi có thể tạo danh sách các tệp cần được di chuyển ở dạng csv hoặc bất kỳ định dạng văn bản nào khác.

Những gì tôi cần làm là chạy một tập lệnh bash và di chuyển hoặc sao chép các tệp được liệt kê trong tệp văn bản sang thư mục khác.

Có một cách dễ dàng để làm điều này? Bất kỳ đề xuất hoặc tài nguyên sẽ được đánh giá rất cao.


Ngoài ra, các tập tin được đặt tên ngẫu nhiên khi chúng được thêm vào thư mục. Không có quy ước đặt tên hoặc bất kỳ logic nào có thể được sử dụng để di chuyển các tệp cụ thể.
Jestep

Câu trả lời:


26

rsync có một số tùy chọn mà có thể mất một danh sách các tập tin vào quá trình ( --files-from, --include-from, vv).

Ví dụ, điều này sẽ thực hiện thủ thuật:

rsync -a /source/directory --files-from=/full/path/to/listfile /destination/directory

2
ví dụ:rsync -a /source/directory --files-from=/full/path/to/listfile /destination/directory
anneb

28

Để tránh việc sử dụng vô ích cat(và nếu bạn không sử dụng rsync):

xargs -a file_list.txt mv -t /path/to/dest

Điều này sẽ xử lý bất kỳ tên tệp hợp lệ, trừ khi nó chứa một dòng mới, nếu các tệp được liệt kê một tên trên mỗi dòng.


2
Một nhược điểm của phương pháp này là nếu các tệp trong danh sách chứa tên đường dẫn (nghĩa là chúng không phải là tất cả trong cùng một thư mục), việc sử dụng mvsẽ thu gọn tất cả chúng vào cùng một thư mục đích. Cách rsynctiếp cận trong câu trả lời được chấp nhận không bị giới hạn này.
Jason R

Ngoài ra, tôi đã thử lệnh này và xargs sẽ phá vỡ mọi tệp có chứa một trích dẫn ("trích dẫn duy nhất chưa từng có")
James Beninger

Điều này làm việc cho tôi vì tôi thực sự muốn các tệp từ các đường dẫn nguồn khác nhau trong cùng một thư mục đích.
PseudoNiri

15
for file in `cat listoffiles`; do mv "$file" /path/of/destination ; done

giả sử bash, cộng với listoffileschứa một tệp trên mỗi dòng. Sự phản đối duy nhất của tôi đối với tuyến rsync là OP yêu cầu phương pháp di chuyển các tệp chứ không sao chép chúng. rsync có nhiều cờ hơn một đám cưới hoàng gia, vì vậy tôi chắc chắn rằng nó có thể được sửa đổi thêm để làm điều đó, nhưng đôi khi đơn giản hơn là tốt hơn!


1
Giải pháp này đánh tôi là linh hoạt nhất. Tôi đã kết thúc việc sử dụng nó với rsync thay vì cp hoặc mv chỉ vì tôi cần tùy chọn đường dẫn tệp tương đối.
Spamwich

4
Thật tuyệt, chỉ là tôi gặp vấn đề với không gian, vì vậy tôi đã sửa đổi nó thành:while read -r file; do mv "$file" /path/of/destination ; done < listoffiles
user1182474

1
@ user1182474 Cảm ơn và cách sử dụng chuyển hướng đầu vào thanh lịch. Bằng cách này, phương pháp truyền thống thể hiện sự hài lòng với một câu trả lời là upvote!
MadHatter hỗ trợ Monica

1
@ user1182474 cảm ơn bạn vì điều đó! Bước cuối cùng trong nhiều sửa đổi đã phải thực hiện một cách mù quáng để chuyển các tiện ích sao lưu OSX của tôi sang Android!
Charlie Gorichanaz

4

Điều này phụ thuộc vào định dạng của tệp văn bản bạn có. Ví dụ: nếu bạn có danh sách các tệp được viết sao cho Mỗi tệp được đặt trên một dòng mới. Bạn có thể sử dụng xargs như:

$ cat your_text_file | xargs cp -t /path/to/destination

Ngoài ra, bạn có thể sử dụng findlệnh với -exectùy chọn. để sao chép / di chuyển các tập tin.


3
rsync --files-from=file_list.txt /path/to/source/ /path/to/dest/

Rsync có thêm lợi ích so với các lệnh cphoặc mvbởi vì nó sẽ tự động tạo các thư mục nếu chúng không tồn tại.


Tại sao /path/to/sourcecần thiết khi nó lấy các đường dẫn từ danh sách tập tin?
bzero

@bzero có thể danh sách các tập tin có thể chứa đường dẫn tương đối?
DreadfulWeather

2

Tôi nghĩ rằng câu trả lời rsync là một câu trả lời tốt hơn, nhưng chỉ cho một tùy chọn khác:

tar -cf - -T FILE_OF_FILENAMES_TO_MOVE.txt |(cd /path/to/new/dir && tar -xvf -)

Điều này tốt cho Dockerfile, vì tar có sẵn trong hình ảnh cơ sở của Ubuntu, nhưng không phải là rsync.
kristianp

1

Tôi vô tình sao chép toàn bộ nội dung của một thư mục vào một thư mục đích thay vì di chuyển toàn bộ thư mục. Điều này dẫn đến một thư mục đích lộn xộn thay vì thư mục gốc được thêm vào thư mục.

Để khắc phục điều này, tôi đã làm như sau:

ls -rt /path/to/cluttered/destination/directory/ > /opt/dircheck/filestomove Lệnh trên tạo tệp filestomove sẽ là danh sách tất cả nội dung của thư mục đích, được sắp xếp ngược theo thời gian, nghĩa là cũ nhất đến mới nhất.

Sau đó, tôi tạo một thư mục con của thư mục đích bây giờ lộn xộn để di chuyển công cụ vào.

mkdir /path/to/cluttered/destination/directory/newsubdirectory

Sau đó, tôi lặp lại danh sách thư mục, ngoại trừ liệt kê ra màn hình và hiển thị thêm chi tiết.

ls -lrht /path/to/cluttered/destination/directory/ Dòng này liệt kê thư mục, được sắp xếp theo ngày tăng dần (sắp xếp ngược theo thời gian) và hiển thị thêm thông tin, bao gồm cả dấu ngày / thời gian của mỗi tệp trong thư mục đích lộn xộn. Tôi đề cập đến điều này, bắt đầu từ đầu để hiển thị những thư mục và tập tin tôi muốn giữ ở đâu. Sẽ có một khoảng trống trong dấu ngày / giờ của các tệp nơi tất cả các tệp mới bắt đầu không nên ở đó.

Sau đó, tôi chỉnh sửa tệp filestomove được tạo ở bước đầu tiên ở trên (được sắp xếp theo ngày) và xóa một vài trong danh sách mà trước đó tôi muốn ở lại thư mục gốc.

vim /opt/dircheck/filestomove Xóa từ đầu, tất cả các tệp bạn không muốn di chuyển.

Sau đó, tôi đã sử dụng lệnh được liệt kê trước đây trong bài đăng này để di chuyển các tệp trong danh sách của tôi sang thư mục mới tôi đã thực hiện.

sudo xargs -a /opt/dircheck/filestomove mv -t /path/to/cluttered/destination/directory/newsubdirectory

Điều này di chuyển tất cả các tập tin trong một tích tắc. (Lưu ý: ban đầu bạn có thể không cần sudo, đây là vấn đề về quyền của tệp).

Bây giờ thư mục đích ban đầu của tôi rất đẹp và sạch sẽ và chứa một thư mục mới với tất cả các tệp và thư mục đang làm lộn xộn nó.


1

Nếu (và chỉ nếu), bạn không có bất kỳ ký tự khó chịu nào trong tên tệp (dấu cách, dòng mới, sẽ gây nhầm lẫn cho xargs về cách chia mọi thứ thành các đối số riêng lẻ) và bạn tạo một danh sách các tệp được phân tách bằng dòng mới (một tệp trên mỗi dòng), bạn có thể làm một cái gì đó như.

cat filenames.txt | xargs mv -t /path/to/move/files/to

(Nói chung, xem man xargs , thật tuyệt vời)

Nếu mv cụ thể của bạn không có tùy chọn -t, bạn cũng có thể thực hiện một số thủ thuật như

( cat filenames.txt; echo; echo /path/to/move/files/to ) | xargs mv

Lưu ý - cả hai sẽ không hoạt động như mong đợi nếu có tên tập tin với dòng mới trong đó.


Tuy nhiên; xem câu trả lời của Ignacio, rsync được sắp xếp theo thứ tự này.
Kjetil Joergensen

cp, mvVà những thứ tương tự không có -ttùy chọn trên bsd 's, và ví dụ thứ hai với subshell không làm việc cho tôi ( /path/to/moveđược nối như tên tập tin cuối cùng)

1
@ w17t - âm thanh như filenames.txt không kết thúc bằng một dòng mới, hoặc thêm dòng mới vào cuối filenames.txt hoặc làm một cái gì đó như(cat filenames.txt; echo; echo /path/to/move/files/to) | xargs mv
Kjetil Joergensen

0

Hãy thử một cái gì đó như:

cat list.txt | while read line; do mv "$line" /images; done

có thể while read line; do mv $line /images; done < list.txt là một lệnh duy nhất
bỏ qua

0

Phần sau đây hoạt động với tôi khi tôi cần sao chép tất cả các tệp PNG từ một đường dẫn cụ thể (và tất cả các thư mục con) sang một vị trí mới trong khi duy trì cấu trúc thư mục:

rsync -av --prune-empty-dirs --include='*/' --include='*.png' --exclude='*' source/ destination/

Bởi vì RSYNC tạo bản sao của cấu trúc thư mục trước, sau đó đồng bộ hóa các tệp, bạn có thể kết thúc với các thư mục dư thừa trống. Tôi đã sử dụng cờ --prune-blank-dirs để xóa các thư mục trống này.

Tôi không có liên kết, nhưng nghĩ rằng việc cấp tín dụng cho nguồn đã truyền cảm hứng cho giải pháp này: http://techblog.zabuchy.net/2011/transfer-only-selected-file-types-with-rsync/

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.