Sao chép một tập tin vào nhiều thư mục bằng cp


12

Câu hỏi này là phần tiếp theo của câu hỏi trước đây của tôi, Tạo nhiều thư mục bằng cách sử dụngmkdir .

Tôi đang sử dụng bashvỏ. Tôi đã tạo năm mươi thư mục, mỗi thư mục bắt đầu bằng tiền tố "s", sử dụng lệnh:

mkdir $(printf "s%02i " $(seq 1 50))

mà đệm đến chữ số thứ hai với số không. Đó là, các thư mục mà tôi có được có dạng s01, s02, ..., s49, s50.

Bây giờ tôi muốn sử dụng cpđể sao chép một tệp duy nhất (ví dụ test.txt:) vào mỗi năm mươi thư mục. Có thể làm điều này theo cách tương tự như trên? Ví dụ, sẽ làm việc sau đây? Tôi còn khá mới đối với Unix / Linux, vì vậy tôi không thực sự muốn thử điều này cho đến khi ai đó làm ơn cho tôi một dấu hiệu cho thấy nó an toàn.

cp test.txt $ (printf "s% 02i.txt" $ (seq 1 50))

Tuy nhiên, nhìn vào mantrang cp, có vẻ như không cphỗ trợ nhiều điểm đến như thế này, tuy nhiên:

NAME
       cp - copy files and directories

SYNOPSIS
       cp [OPTION]... [-T] SOURCE DEST
       cp [OPTION]... SOURCE... DIRECTORY
       cp [OPTION]... -t DIRECTORY SOURCE...

DESCRIPTION
       Copy SOURCE to DEST, or multiple SOURCE(s) to DIRECTORY.

       Mandatory  arguments  to  long  options are mandatory for short options
       too.

Câu trả lời:


7

Nếu bạn muốn sử dụng đầu ra từ lệnh của mình để sao chép tệp vào từng thư mục bằng cách sử dụng cp, bạn luôn có thể chuyển nó sang xargs:

printf "s%02i " $(seq 1 50) | xargs -n 1 cp test.txt

Không nên có bất kỳ lo ngại nào về sự an toàn của việc phân tích cú pháp đầu ra vì bạn biết trước định dạng và nội dung của nó - nguy cơ gặp phải các ký tự meta và khoảng trắng trong tên tệp không thực sự là vấn đề ở đây.

Ngoài ra, giả sử các thư mục đã tồn tại, bạn có thể thử một cái gì đó như:

find . -maxdepth 1 -type d -name 's[0-9][0-9]' -print0 | xargs -0 -I {} cp test.txt {}

hoặc không có đường ống:

find . -maxdepth 1 -type d -name 's[0-9][0-9]' -exec cp test.txt {} \;

Hai lệnh cuối cùng sẽ tìm thấy bất kỳ tệp nào trong thư mục hiện tại và cp test.txtcho chúng. Các -maxdepth 1tùy chọn sẽ tránh được bất kỳ thư mục con nhận đủ hồ sơ là tốt. Được cảnh báo rằng 's[0-9][0-9]'khớp với shai chữ số bất kỳ, có nghĩa là nếu vì lý do nào đó bạn có s99trong cwdđó, nó cũng sẽ nhận được một bản sao test.txt.


8

Bạn cũng có thể để shell thực hiện các vòng lặp với một forvòng lặp. Đây là cách cơ bản nhất không phụ thuộc vào các công cụ bên ngoài như parallelhoặc xargs, và tôi thấy dễ hiểu nhất:

for name in $(printf "s%02i " $(seq 1 50)); do
    mkdir $name
    cp test.txt $name
done

Có một triệu cách khác để viết này, ví dụ:

for name in $(seq -w 1 50); do
    mkdir s$name
    cp test.txt s$name
done

Nếu bạn muốn xác minh những gì sẽ được thực hiện trước khi thực hiện nó, bạn có thể làm một cái gì đó như chuẩn bị các lệnh với echo, nó sẽ in dòng thay vì thực thi nó:

for name in $(seq -w 1 50); do
    echo mkdir s$name
    echo cp test.txt s$name
done

đầu ra:

mkdir s01
cp test.txt s01
mkdir s02
cp test.txt s02
mkdir s03
cp test.txt s03
# etc.


2

Bạn cũng có thể sử dụng GNU song song . Giả sử bạn đang ở trong thư mục chứa text.txt và 50 thư mục của bạn được đặt trong /my/50dirs/path(như /my/50dirs/path/s01, /my/50dirs/path/s02v.v.) bạn sẽ chạy:

seq -w 01 50 | parallel -j1 cp text.txt /my/50dirs/path/s{}

2
Tốt hơn là làm điều đó parallel -j1, nếu không sẽ có một công việc cho mỗi lõi và trên máy đa lõi, các công việc sẽ cạnh tranh cho IO.
Gilles 'SO- ngừng trở nên xấu xa'
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.