Tôi có một thư mục có tên /home/user/temps487 thư mục. Trong mỗi thư mục tôi có một tập tin gọi là thumb.png.
Tôi muốn sao chép tất cả các tệp có tên thumb.png vào một thư mục riêng và đổi tên chúng dựa trên thư mục mà chúng đến.
Tôi có một thư mục có tên /home/user/temps487 thư mục. Trong mỗi thư mục tôi có một tập tin gọi là thumb.png.
Tôi muốn sao chép tất cả các tệp có tên thumb.png vào một thư mục riêng và đổi tên chúng dựa trên thư mục mà chúng đến.
Câu trả lời:
Ở đây bạn đi:
for file in /home/user/temps/*/thumb.png; do new_file=${file/temps/new_folder}; cp "$file" "${new_file/\/thumb/}"; done;
biên tập:
Nhân tiện, sự khôn ngoan kinh điển là việc sử dụng findcho điều này là một ý tưởng tồi - chỉ đơn giản là sử dụng mở rộng vỏ là đáng tin cậy hơn nhiều. Ngoài ra, điều này giả định bash, nhưng tôi cho rằng đó là một giả định an toàn :)
chỉnh sửa 2:
Để rõ ràng, tôi sẽ phá vỡ nó:
# shell-expansion to loop specified files
for file in /home/user/temps/*/thumb.png; do
# replace 'temps' with 'new_folder' in the path
# '/home/temps/abc/thumb.png' becomes '/home/new_folder/abc/thumb.png'
new_file=${file/temps/new_folder};
# drop '/thumb' from the path
# '/home/new_folder/abc/thumb.png' becomes '/home/new_folder/abc.png'
cp "$file" "${new_file/\/thumb/}";
done;
chi tiết về ${var/Pattern/Replacement}cấu trúc có thể được tìm thấy ở đây .
các trích dẫn trong cpdòng rất quan trọng để xử lý các khoảng trắng và dòng mới, v.v. trong tên tệp.
new_file/\/thumbgì?
${VARIABLE/PATTTERN/REPLACEMENT}tạo ra giá trị của VARIABLEnhưng với mẫu thay thế bằng văn bản thay thế. Ở đây mô hình là /thumb( /nhu cầu được thoát ra sao cho nó không giống như thế ${new_file//PATTERN/REPLACEMENT}, điều này làm cho nó thay thế toàn cầu thay vì thay thế lần đầu tiên) và văn bản thay thế trống rỗng.
/home/user/temps, điều này không rõ ràng trong câu hỏi. Nếu họ không, bạn cần tìm hoặc **.
Điều này làm việc cho các thư mục con sâu tùy ý:
$ find temps/ -name "thumb.png" | while IFS= read -r NAME; do cp -v "$NAME" "separate/${NAME//\//_}"; done
`temps/thumb.png' -> `separate/temps_thumb.png'
`temps/dir3/thumb.png' -> `separate/temps_dir3_thumb.png'
`temps/dir3/dir31/thumb.png' -> `separate/temps_dir3_dir31_thumb.png'
`temps/dir3/dir32/thumb.png' -> `separate/temps_dir3_dir32_thumb.png'
`temps/dir1/thumb.png' -> `separate/temps_dir1_thumb.png'
`temps/dir2/thumb.png' -> `separate/temps_dir2_thumb.png'
`temps/dir2/dir21/thumb.png' -> `separate/temps_dir2_dir21_thumb.png'
Phần xen kẽ là phần mở rộng tham số ${NAME//\//_} . Nó có nội dung NAMEvà thay thế mọi lần xuất hiện của /với _.
Lưu ý: kết quả phụ thuộc vào thư mục làm việc và tham số đường dẫn cần tìm. Tôi đã thực thi lệnh từ thư mục mẹ của temps. Thay thế cpbằng echođể thử nghiệm.
Mã trợ giúp ngắn:
#!/bin/bash
#
# echo cp "$1" ../tmp/"${1//\//_}"
#
mv "$1" ../tmp/"${1//\//_}"
hãy đặt tên cho nó là 'deslash.sh' và làm cho nó có thể thực thi được. Gọi nó với:
find -type f -name thumb.png -exec ./deslash.sh {} ";"
Nó sẽ thất bại, nếu một vụ va chạm tồn tại
a/b/thumb.png # and
a_b/thumb.png
nhưng đó là điều không thể tránh khỏi.
Thử đi
mkdir /home/user/thumbs
targDir=/home/user/thumbs
cd /home/user/temps
find . -type d |
while IFS="" read -r dir ; do
if [[ -f "${dir}"/thumb.png ]] ; then
echo mv -i "${dir}/thumb.png" "${targDir}/${dir}_thumb.png"
fi
done
Biên tập
Tôi đã thêm trích dẫn trong trường hợp bất kỳ tên dir nào của bạn có ký tự khoảng trắng được nhúng trong chúng.
Ngoài ra tôi đã thay đổi điều này để nó sẽ chỉ in ra các lệnh sẽ được thực thi. Kiểm tra đầu ra của tập lệnh để đảm bảo tất cả các tên tệp / đường dẫn trông phù hợp. Khi bạn chắc chắn không có vấn đề gì với các lệnh sẽ được thực thi, hãy xóa echo.
mv -i ./A A/thumb.png ../tmp/.png- tất cả các tệp kết thúc bằng ../tmp/.png (../tmp là thư mục tiêu của tôi).
find -type dvà xem đầu ra. Điều đó có nhận được tất cả các thư mục bạn mong đợi? Nó nên, nếu không, xin vui lòng thêm một số đầu ra để hiển thị vấn đề. Chúc may mắn.
read dirthực hiện phân tách từ và lấy, từ một thư mục a\nba và b làm hai trường hợp mà không có mặt nạ nào có thể giải quyết.
Để sao chép, bạn cần lệnh cp và đổi tên cho linux cũng giống như di chuyển tệp, vì vậy bạn phải thực hiện bằng lệnh mv . Trong Linux, bạn luôn phải chỉ định toàn bộ đường dẫn, từ nguồn, nếu bạn đang ở trong một thư mục khác, và đến thư mục đích, tất nhiên. Tôi sẽ là một cái gì đó như thế này, để sao chép:
cp /source_path/file /destination_path/
hoặc đổi tên hoặc di chuyển
mv /source_path/old_file /destination_path/new_name_file