Làm thế nào để đổi tên tập tin và thay thế các ký tự?


11

Tôi có một nhóm các tập tin có :(dấu hai chấm) trong tên. Tôi cần phải thay thế :bằng -(dấu gạch ngang).

Có một cách dễ dàng để làm điều này trong một kịch bản?

Tên tệp mẫu: 2013-10-11:11:52:08_055456663_045585_.txt

Câu trả lời:


16

Một lớp lót đơn giản nên làm (giả sử shvỏ tương thích Posix ):

for f in *:*; do mv -v "$f" $(echo "$f" | tr ':' '-'); done

Giải trình:

  • for ... in ...; do ...; donelà một vòng lặp

  • *:* phù hợp với tất cả các tệp và thư mục trong thư mục hiện tại có :tên của chúng

  • f được gán lần lượt cho từng tên tệp như vậy trong vòng lặp

  • mvđổi tên đối số thứ nhất thành đối số thứ hai; -v(verbose) yêu cầu nó in những gì nó làm; tùy chọn này là GNU-utils cụ thể, vì vậy nó có sẵn trên Linux nhưng không có Solaris

  • $(...) thực thi mã trong một vỏ con và thay thế đầu ra

  • echo in đối số của nó lên đầu ra tiêu chuẩn

  • tr đọc đầu ra tiêu chuẩn và dịch các ký tự theo bản đồ được cung cấp

Nếu bạn đang sử dụng bash , bạn có thể tránh sinh ra một shell ( $()) bằng các quy trình con ( tr) bằng cách thay thế $(...)bằng ${f//:/-}.


+1 cho một câu trả lời đơn giản, mặc dù nó có thể giải thích thêm một chút. Ví dụ: for f invòng lặp ... là một vòng lặp lặp lại trên tất cả các tệp trong thư mục hiện tại nơi các tệp cần khớp *:*. (Điều gì xảy ra với dirs phù hợp?). Lệnh di chuyển là một tên mới di chuyển oldname trong đó tên mới được tạo bằng cách thực hiện một shell với $( subshell here ). Những gì tr làm, ...
Hennes

@ Hennes: đây là siêu người dùng - tôi có thực sự cần phải đi sâu vào các loại chi tiết này không? Ồ, ở đây bạn đi ...
sds

Không. Nếu có nhu cầu thực sự thì tôi sẽ không có + 1'ed. Và tôi hiểu những gì nó làm. Tôi nghĩ rằng nó là tốt đẹp cho nhiều độc giả khác mặc dù.
Hennes

2
Bạn có thể thay thế $(echo "$f" | tr ':' '-')bằng "${f//:/-}"và tránh cuộc gọi phụ, đường ống và chương trình bên ngoài. Tôi nghĩ rằng đây là một bashism, nhưng eh. Xem tại đây .
evilsoup

@evilsoup Thật vậy; nó không tạo ra nhiều khác biệt cho các tập dữ liệu nhỏ (và người ta có thể ủng hộ khả năng đọc) nhưng bạn sẽ ngạc nhiên khi thấy một thứ như thế nhanh đến mức nào. Tôi đã nhận được một chút bởi nó gần đây; viết lại một tập lệnh sao cho hai lệnh tạo chuỗi đơn giản không còn cần thiết dễ dàng cắt giảm thời gian thực hiện từ 90% trở lên, mà trên một tập dữ liệu lớn được dịch thành vài phút thời gian chạy đồng hồ.
một CVn

6

Như đã nêu trong một bài viết khác của tôi, renamecông cụ có thể thực hiện thủ thuật cho bạn. Bạn chỉ cần gõ rename s/:/-/ <files to rename> Điều này thay thế mỗi dấu hai chấm bằng dấu gạch ngang trong tất cả các tệp bạn đặt tên ở cuối, nghĩa là2013-10-*

Đây là liên kết đến bài viết khác của tôi


1

Tôi chắc chắn một UNIX pro có thể làm điều này với bash, nhưng đây là phiên bản nhanh và bẩn của tôi với ruby.

path_to_files = "/home/username/wrongnames/"
filenames = `ls #{path_to_files}`.split
filenames.each do |fn|
  `mv #{path_to_files + fn} #{path_to_files + fn.gsub(/:/, "-")}`
end

đặt path_to_files thành đường dẫn đến các tệp được đặt tên sai của bạn. lưu mã trên vào một tệp có tên là rename.rb rồi:

username@machinename$ ruby rename.rb

@sds cung cấp một câu trả lời tốt hơn nhiều. Tôi có nên xóa câu trả lời của mình? Tôi mới sử dụng stackoverflow.
shupru

1
Không; nó vẫn có giá trị đáng kể :)
Blacklight Shining

2
Có một vài nhược điểm lớn với câu trả lời này, tuy nhiên, điều đó có thể có liên quan và chắc chắn đáng để biết. (Nó vẫn có thể hữu ích, nhưng hãy cẩn thận và tất cả những thứ đó.) Về cơ bản, có vẻ như nó sẽ bị hỏng nặng khi gặp tên tệp có khoảng trắng (không chỉ là dòng mới trong trường hợp thất bại cổ điển). Ngoài ra, ngay cả khi nó không dành cho khoảng trắng, bạn nên trích dẫn tên tệp trong lệnh gọi shell để bảo vệ bất kỳ ký tự đặc biệt nào khác trong tên tệp khỏi vỏ (mặc dù tôi không biết chính xác cách hoạt động của toán tử backtick của Ruby ).
một CVn

1

Nếu bạn chỉ có một hoặc một vài tệp, điều này có thể thực hiện việc đổi tên cho bạn:

  1. Lưu mẫu của tên tệp bạn đang nhắm mục tiêu dưới dạng một biến : p="201*".
  2. Lưu trữ tên tệp cũ mà bạn muốn đổi tên : old_name=$(ls | grep $p).
  3. Lưu trữ tên tệp mới với các ký tự thay thế cần thiết:

    new_name=$(ls | grep $p | sed 's/:/_/g')        # Using 'sed'
    
                OR
    
    new_name=$(ls | grep $p | tr ':' '_')           # Using 'tr'
    

Tiền thưởng dọn dẹp :
  a. Nếu vì sự đồng nhất, bạn muốn thay thế dấu gạch ngang (-) cùng với dấu hai chấm (:) bằng dấu gạch dưới (_), bạn có thể làm điều này:

    new_name=$(ls | grep $p | tr ':-' '_');

  b. Nếu bạn cũng muốn dấu gạch dưới cuối cùng (ngay trước khi .txt), hãy đặt new_namebiến là:

    new_name=$(ls | grep $p | tr ':-' '_' | sed 's/_\./\./')
  1. Bây giờ đổi tên tập tin của bạn khi cần thiết: mv $old_name $new_name

         NB: mvsẽ thất bại nếu bất kỳ tên tệp nào trong thao tác đổi tên có spacestrong đó. Trong trường hợp đó, bọc các biến thích hợp trong dấu ngoặc kép, như:
mv "$old_name" $new_name HOẶC mv $old_name "$new_name" HOẶC mv "$old_name" "$new_name"


Một lớp lót

1a: p="201*"; old_name=$(ls | grep $p); new_name=$(ls | grep $p | sed 's/:/_/g'); mv $old_name $new_name

1b: p="201*"; old_name=$(ls | grep $p); new_name=$(ls | grep $p | tr ':' '_'); mv $old_name $new_name

2: p="201*"; old_name=$(ls | grep $p); new_name=$(ls | grep $p | tr ':-' '_'); mv $old_name $new_name

3: p="201*"; old_name=$(ls | grep $p); new_name=$(ls | grep $p | tr ':-' '_' | sed 's/_\./\./'); mv $old_name $new_name

0

sử dụng renamer :

$ renamer --find ":" --replace "-" *

Tôi nghĩ rằng việc cài đặt một môi trường node.js hoàn chỉnh để chỉ đổi tên các tệp là hơi quá nhiều. renamelà một công cụ được cài đặt sẵn trên nhiều bản phân phối linux. Nhưng tôi nghĩ cho Windows công cụ này có thể là tuyệt vời.
noggerl

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.