Đổi tên tập tin với tên đường dẫn của nó


8

Tôi có một tập tin .bdf bên trong các thư mục con. Tất cả .bdf có cùng tên: Loads.bdf

Thí dụ:

/home/user/folderxx/folderxxx/Load.bdf
/home/user/folderxx/folderxxx/Load.bdf

Tôi cần tìm (và sao chép vào một thư mục mới) tất cả các tệp Load.bdf và đổi tên chúng với tên đường dẫn của nó.

Ví dụ: Sau khi hoạt động dự định, nó sẽ hiển thị một cái gì đó như thế này.

folder001_folderAAA_Load.bdf
folder002_folderBBB_Load.bdf

Câu trả lời:


11

Tôi sẽ sử dụng mcpcông cụ từ gói mmv("di chuyển nhiều") cho điều đó:

mcp '/home/user/*/*/Load.bdf' '#1_#2_Load.bdf'

Các #1, #2vv trong chuỗi thứ hai sẽ được thay thế bằng nội dung của 1 tương ứng vv wildcard thứ 2 từ chuỗi đầu tiên. Lưu ý rằng đường dẫn nằm trong dấu ngoặc đơn để các ký tự đại diện được diễn giải bằng mcp, không phải bằng vỏ.

Với lệnh được hiển thị, các tệp sẽ được sao chép vào thư mục hiện tại. Nếu bạn thay thế mcpbằng mmv, các tập tin sẽ được di chuyển thay thế.


Chuỗi trích dẫn kép cũng không có mở rộng ký tự đại diện, ít nhất là trong bash.
Daniel Beck

Điều này hữu ích với tôi để sao chép tên của thư mục vào mỗi tệpmmv '*/*.m4a' '#1.m4a'
ajr-dev

5

Sử dụng prename(bí danh cho renamenhiều hệ thống) có thể thực hiện việc này mà không cần chạy nhiều lần mvhoặc cp:

cd /home/user
find . -type f -name 'Loads.bdf' -exec \
  prename -n 's:^./::; s:/:_:g; s:^:destination/:' {} +

Xóa -nkhi bạn chắc chắn điều này đang di chuyển các tệp bạn muốn.

Cập nhật

Để sao chép các tệp thay vì di chuyển chúng, cách nhanh nhất là sao chép trước bằng cpiohoặc paxsau đó đổi tên như trước. Ví dụ: (với GNU cpio):

cd /home/user
find . -type f -name 'Loads.bdf | cpio -p --make-directories destination

cd destination
find . -type f -name 'Loads.bdf' -exec  prename -n 's:^./::; s:/:_:g' {} +

Lưu ý rằng mặc dù paxlà cả POSIX và LSB và cpiokhông còn là POSIX, cpionhưng đây vẫn là chương trình thường được tìm thấy ở nhiều hệ thống.

Để xử lý tên tập tin với dòng mới với GNU find/ cpiongười ta có thể thêm -print0vào find-0để cpio.

Cập nhật 2

Các paxgiải pháp là một lớp lót (không bao gồm cd):

cd /home/user
find . -name 'Loads.bdf' | cut -d/ -f 2- | pax -rws ':/:_:g' destination

Hoặc cho bất kỳ tên tệp (và GNU find):

find /home/user -name 'Loads.bdf' -printf '%P\0' | pax -0rws ':/:_:g' destination

hai tên , một perl (hay còn prenamegọi là renamemặc định trong Ubuntu) và một cái khác không sử dụng regex (được gọi là renametrên Arch và Red Hat). Ngoài ra, -execdirđược ưa thích để -exec(xem man find). Cuối cùng, không phải lệnh này di chuyển các tập tin, không sao chép chúng?
Sparhawk

@Sparhawk, vâng đó là lý do tại sao tôi chỉ định prename. Mặc dù tôi đã bỏ lỡ phần 'copy` trong câu hỏi.
Graeme

À không sao (đó là một chỉnh sửa?). Có lẽ tôi chỉ đọc sai.
Sparhawk

@Sparhawk, không chỉnh sửa. Cuộc gọi tốt khi di chuyển so với bản sao mặc dù tôi đã thêm một giải pháp cập nhật ngay bây giờ.
Graeme

1
@Tim, được cập nhật với paxgiải pháp, nó có tùy chọn tìm / thay thế riêng.
Graeme

3

Nếu bạn tình cờ cần phải làm điều này trên một hệ thống không có các công cụ được đề cập trong một số câu trả lời khác (như mcp và mmv hoặc prename) và bạn muốn thực hiện hoàn toàn trong trình bao, bạn có thể làm gì đó giống:

#!/usr/bin/env bash

oldpath="/home/user"
newpath="/home/user/newfolder"

for file in $(find $oldpath -type f -name Load.bdf); do
        shortname=${file#$oldpath/}
        newname="$newpath/${shortname//\//_}"
        if [ -f $newname ]; then
                echo "$newname already exists."
        else
                echo "copy: $file"
                echo "  --> $newname"
                cp $file $newname
        fi
done

Tập lệnh này sẽ tìm tất cả các tệp có tên Load.bdftrong oldpaththư mục, chuyển tên thư mục thành tên tệp mới và sao chép chúng vào thư mục đích của bạn. Chúng tôi cũng có thể kiểm tra sự tồn tại của các tệp đã được sao chép, trong trường hợp bạn cần chạy nó nhiều lần và chúng tôi không cần phải sao chép lại tất cả các tệp.

Cấu trúc thư mục kết quả sẽ trông giống như:

bash$ find . -type f
/home/user/folder001/folderAAA/Load.bdf
/home/user/folder002/folderBBB/Load.bdf
/home/user/folder003/folderCCC/Load.bdf
/home/user/newfolder/folder001_folderAAA_Load.bdf
/home/user/newfolder/folder002_folderBBB_Load.bdf
/home/user/newfolder/folder003_folderCCC_Load.bdf

cảm ơn tất cả thông tin của bạn tôi đã nhận được nhiều thông tin hơn những gì tôi cần. cám ơn bạn một lần nữa.
sh999

1
Tuyệt vời .. bạn cũng có thể thuê ngoài tất cả logic tồn tại của tệp cho cp noclobber bằng cách bỏ toàn bộ if /
other


0
env - sh <<\SCRIPT

    t=/home/user/target f=folder
    cd "${t%/*}" && mkdir -p "$t"
    set -- $f??/$f???/Load.BDF
    while [ -e "$1" ] ; do
        cp "$1" "$t/$(IFS=/
            printf '%s_%s_%s\n' $1)"
    shift ; done

SCRIPT

Tôi nghĩ rằng đây là tất cả các kịch bản shell hoàn toàn di động - và nó được thực hiện khá đơn giản, mặc dù lúc đầu tôi đã nghi ngờ.

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.