Đổi tên nhiều tệp bằng cách sử dụng tập lệnh Bash


27

Tôi muốn đổi tên nhiều tệp trong cùng một thư mục bằng cách sử dụng tập lệnh Bash. Tên của các tập tin như sau:

file2602201409853.p
file0901201437404.p  
file0901201438761.p  
file1003201410069.p  
file2602201410180.p

Tôi muốn đổi tên thành định dạng sau:

file2503201409853.p
file2503201437404.p  
file2503201438761.p  
file2503201410069.p  
file2503201410180.p

Tôi đã đọc về lệnh đổi tên, và cố gắng thực hiện theo cách này, nhưng nó không làm gì cả, tôi nghĩ rằng tôi có câu hỏi về cú pháp. Sau đó tôi đọc rằng bạn có thể tạo một vòng lặp bằng lệnh mv như sau:

for file in cmpsms*2014*.p; do
    mv "$file" "${file/cmpsms*2014*.p/cmpsms25032014*.p}"
done

Nhưng tôi không thể đổi tên các tập tin. Tôi đang làm gì sai?



2
Bạn không thể có biểu thức mẫu ở phía bên phải của biểu thức thay thế mở rộng tham số. Những gì bạn đã mong đợi là nơi đó *là?
kojiro

@Kiwy Câu hỏi đó là về việc loại bỏ một phần tên tệp. Ergo, rất nghi ngờ trùng lặp.
một CVn

2
Lần tới, vui lòng mô tả các thay đổi tên tệp bạn muốn thực hiện (tôi phải xem xét điều này cho công bằng trong khi trước khi thấy sự khác biệt và tương đồng). Các ví dụ là tốt, nhưng một mô tả cũng như các ví dụ thậm chí còn tốt hơn.
CVn

Câu trả lời:


42

Bạn đã đúng khi xem xét đổi tên trước. Cú pháp hơi lạ nếu bạn không quen sử dụng regex nhưng nó là con đường nhanh nhất / ngắn nhất một khi bạn biết bạn đang làm gì:

rename 's/\d{4}/2503/' file*

Điều đó chỉ đơn giản là khớp với 4 số đầu tiên và hoán đổi chúng cho những số bạn đã chỉ định.

Và khai thác thử nghiệm ( -vncó nghĩa là dài dòng nhưng không làm gì cả) bằng tên tệp của bạn:

$ rename 's/\d{4}/2503/' file* -vn
file0901201437404.p renamed as file2503201437404.p
file0901201438761.p renamed as file2503201438761.p
file1003201410069.p renamed as file2503201410069.p
file2602201409853.p renamed as file2503201409853.p
file2602201410180.p renamed as file2503201410180.p

8
Lưu ý rằng đây là đổi tên Perl trên Debian và các công cụ phái sinh (Ubuntu, Mint, cám). Trên các bản phân phối Linux khác, renamelà một công cụ đổi tên tệp hoàn toàn khác (mà Debian vận chuyển như rename.ul).
Gilles 'SO- ngừng trở thành ác quỷ'

Nếu phân phối của bạn thiếu công cụ như vậy, hãy xem câu trả lời @Michael Campbell. Tôi nghĩ rằng mọi phân phối thay thế mặc định renamenhư debian đã làm.
Astery

25

Cái này cần phải dùng mẹo:

for f in file*; do mv $f ${f/${f:4:8}/25032014}; done

Nó thay thế chuỗi giữa ký tự thứ 4 và thứ 12 bằng "25032014".


cái này for f in file*; do mv $f ${f/${f:4:4}/2503}; donecũng có tác dụng
Avinash Raj

Điều đó thật tuyệt. Nếu bạn chỉ muốn làm một từ thông thường để thay thế từ, nó hoạt động như sed. ví dụfor f in *Huge*; do mv $f ${f/Huge/Monstrous}; done
Eric

1
@Eric - Tôi đã đăng câu trả lời của bạn như một cách thay thế bởi vì tôi nghĩ nó rõ ràng và thanh lịch hơn. Nếu bạn cũng muốn đăng nó dưới dạng câu trả lời - Tôi sẽ xóa của tôi. Cảm ơn!
Yehosef


Nó báo lỗi cho tôi: "mv: target 'FILE_NAME' không phải là một thư mục"
Aubrey

10

Đây thực sự là câu trả lời của @ Eric từ phía trên - nhưng đó là một câu trả lời tao nhã vì vậy tôi đang đăng lại nó như một câu trả lời thích hợp để thu hút sự chú ý nhiều hơn vào nó.

for f in *Huge*; do mv $f ${f/Huge/Monstrous}; done

1
ptrn='file[0-9][0-9][0-9][0-9]2014[0-9][0-9][0-9][0-9][0-9].p'
path=/dir
( set -- "${path}/"${ptrn} ; for f ; do {
    echo "mv ${path}/${f} \
        ${path}/file25032014${f#2014}" 
} ; done )

Cái này cần phải dùng mẹo. Lưu ý - Tôi không có thói quen bàn giao các lệnh mv hàng loạt - vì được viết nó chỉ là một tiếng vang. Bạn sẽ phải sắp xếp nó ra trước khi nó hoạt động.


1

Một cách đơn giản để làm điều đó mà không cần lặp, với thư mục traversal :

find -type f | xargs -I {} mv {} {}.txt

Nó sẽ đổi tên mọi tập tin tại chỗ.

Và dưới một ví dụ làm việc với sự song song :

find -name "file*.p" | parallel 'f="{}" ; mv -- {} ${f:0:4}2503${f:8}'

Đó là một cách tiếp cận đầu tiên dễ dàng để tưởng tượng giải pháp tốt hơn. Nếu bạn muốn một lệnh làm việc, hãy làm:
dtrckd

find -type f -name "file*.p" | parallel 'ext="{}" ; mv -- {} ${ext:0:4}2503${ext:8}'
dtrckd

0

Nếu bạn thấy bạn làm điều này rất nhiều, hãy tìm "rename.pl". Đó là tập lệnh perl, nhưng cho phép bạn chỉ cần cung cấp mã perl (như biểu thức ///) và nó sẽ thực hiện đổi tên hàng loạt dựa trên biểu thức hoặc mã đó.

Có một phiên bản cơ bản ở đây: http://stackoverflow.org/wiki/Rename.pl nhưng có các phiên bản khác trôi nổi trên mạng. Nó đã được khoảng cho lứa tuổi và lứa tuổi và lứa tuổi.

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.