Tôi đã có một câu trả lời lúng túng quanh đây trước đó, nhưng câu trả lời của Denis nhắc nhở tôi rằng tôi đã bỏ lỡ điều cơ bản nhất. Vì vậy, tôi đã xóa câu trả lời ban đầu của tôi. Nhưng vì không ai nói điều này rất cơ bản, tôi nghĩ rằng đáng để đặt nó ở đây.
Câu hỏi ban đầu là "Tôi có một tệp văn bản với một danh sách các tên tệp được phân tách bằng dấu cách. Làm cách nào tôi có thể sao chép chúng vào một thư mục đích." Lúc đầu, điều này có vẻ phức tạp hoặc phức tạp, bởi vì bạn nghĩ rằng bạn phải trích xuất các mục từ tệp theo cách cụ thể. Tuy nhiên, khi shell xử lý một dòng lệnh, điều đầu tiên nó làm là tách danh sách đối số thành các mã thông báo và (đây là bit không ai nói hoàn toàn) các dấu cách tách biệt . (Dòng mới cũng phân tách mã thông báo, đó là lý do tại sao thử nghiệm của Doug Harris với danh sách được phân tách dòng mới có kết quả tương tự.) Đó là, trình bao mong đợi và có thể xử lý danh sách được phân tách bằng dấu cách.
Vì vậy, tất cả những gì bạn cần làm ở đây là đặt danh sách được phân tách bằng dấu cách (mà bạn đã có) vào đúng vị trí trong lệnh của bạn. Lệnh của bạn là một số biến thể về điều này:
cp file1 file2 file3...file# target
Điều duy nhất là bạn muốn lấy danh sách các tệp từ 1 đến # từ tệp văn bản của mình.
Như Dennis chỉ ra trong nhận xét của anh ấy, nỗ lực ban đầu của bạn ( cp
cat list.txt new_folder
) đã hoạt động. Tại sao? Bởi vì lệnh nội bộ cat list.txt
được xử lý trước bởi shell và mở rộng thành file1 file2 file3...file#
, đó chính xác là những gì shell mong đợi và muốn ở phần đó của lệnh. Nếu nó không hoạt động thì (1) bạn đã mắc lỗi đánh máy hoặc (2) tên tệp của bạn bằng cách nào đó kỳ lạ (chúng có khoảng trắng hoặc các ký tự bất thường khác).
Lý do mà tất cả các câu trả lời của Dennis hoạt động chỉ đơn giản là chúng cung cấp danh sách các tệp cần thiết cp
để làm việc, đặt danh sách đó vào vị trí của nó trong toàn bộ lệnh. Một lần nữa, chính lệnh này là trong cấu trúc:
cp list-of-files target_directory
Thật dễ dàng để thấy tất cả kết hợp với nhau như thế nào trong phiên bản này:
cp $(<list.txt) new_folder
$()
làm cho shell chạy lệnh bên trong dấu ngoặc đơn và sau đó thay thế đầu ra của nó tại điểm đó trong dòng lớn hơn. Sau đó, vỏ chạy toàn bộ dòng. Nhân tiện, đây $()
là phiên bản hiện đại hơn của những gì bạn đã làm với backticks (`). Tiếp theo: <
là một toán tử chuyển hướng tập tin. Nó báo cho shell đổ nội dung của list.txt
đầu vào tiêu chuẩn. Vì $()
bit được xử lý trước, đây là những gì xảy ra trong các giai đoạn:
cp $(<list.txt) new_folder
# split line into three tokens: cp, $(<list.txt), new_folder
cp file1 file2 file3...file# new_folder
# substitute result of $(<list.txt) into the larger command
Rõ ràng bước 2 chỉ đơn giản là cp
lệnh bình thường mà bạn muốn.
Tôi nhận ra rằng tôi đã đánh con ngựa này (có lẽ rất chết) rất nhiều, nhưng tôi nghĩ nó đáng để làm. Hiểu chính xác cách shell xử lý một lệnh có thể giúp bạn viết nó tốt hơn và đơn giản hóa rất nhiều. Nó cũng sẽ cho bạn thấy nơi mà các vấn đề có khả năng được che giấu. Trong trường hợp này, ví dụ, câu hỏi đầu tiên của tôi cho bạn nên là về tên tập tin vui hoặc một lỗi đánh máy có thể. Không cần nhào lộn.