Câu trả lời:
Công rename
cụ đi kèm với Ubuntu khá hấp dẫn với loại công cụ này. Bạn có thể nhúng các biểu thức Perl nhỏ như vậy:
rename -n 's/.+/our $i; sprintf("AS%d.txt", 1+$i++)/e' *
Điều đó sẽ chỉ cho bạn thấy những gì nó sẽ làm. Loại bỏ -n
để làm cho nó một bài tập lửa sống.
Điều này về cơ bản hoạt động bằng cách xác định sơ bộ một biến và tăng nó cho mỗi tệp chúng ta nhấn. Nếu bạn sẽ có nhiều hơn 10 tệp, tôi khuyên bạn nên sử dụng một số phần đệm không trong sprintf
. Sau đây là tốt lên đến 999
:
rename -n 's/.+/our $i; sprintf("AS%03d.txt", 1+$i++)/e' *
... Nhưng nó đủ dễ để mở rộng.
Để cải thiện câu trả lời của @ Oli's , phiên bảnrename
công cụ 1.600 của Aristotle Pagaltzis thực sự có một bộ đếm được tích hợp sẵn $N
.
Vì vậy, tất cả những gì bạn cần là,
rename 's/AS.*/AS$N/' *
Để cài đặt,
brew install rename
hoặc Tải xuống tập lệnh/usr/local/bin/brew
hoặc /usr/bin
)rename
cho phép bạn chỉ định trực tiếp $_
, đó là lý tưởng cho vấn đề này.Mặc dù các đối số mã mà chúng tôi chuyển đến rename
tiện ích Perl thường thực hiện khớp và thay thế (bằng s/
) và hoàn toàn có thể chấp nhận để giải quyết vấn đề này theo cách đó , nhưng thực sự không cần thiết trong trường hợp như thế này khi bạn không thực sự kiểm tra hoặc sử dụng lại văn bản của tên tập tin cũ. rename
cho phép bạn viết bất kỳ mã Perl nào và không cần phải nhúng vào bên trong s/
/e
. Tôi đề nghị sử dụng một lệnh như thế này:
rename -n 'our $i; $_ = sprintf "AS%02d.txt", ++$i' *
Hoặc, nếu bạn cảm thấy muốn cạo sạch một vài ký tự:
rename -n '$_ = sprintf "AS%02d.txt", ++our$i' *
(Nó có thể được thực hiện thậm chí ngắn hơn, nhưng không phải không hy sinh sự rõ ràng.)
Cả hai lệnh này đều làm điều tương tự. Mỗi chương trình cho thấy các hoạt động đổi tên sẽ được thực hiện. Khi bạn thử một lần và bạn hài lòng với kết quả, hãy chạy lại mà không có -n
tùy chọn. Theo văn bản, điều này sẽ tạo ra tên tập tin AS01.txt
, AS02.txt
, ..., AS10.txt
, AS11.txt
, và vân vân. Bạn có thể sửa đổi chúng khi cần, sau đó chỉ xóa -n
khi bạn thích những gì bạn thấy.
Nếu bạn muốn đệm đến chiều rộng lớn hơn 2, hãy thay thế 2
bằng số lớn hơn. Ví dụ: nếu vì lý do nào đó bạn muốn tên tệp như thế AS00000000000001.txt
, bạn sẽ thay thế %02d
bằng %014d
. Nếu bạn hoàn toàn không muốn đệm - mặc dù điều đó sẽ làm cho các tệp của bạn xuất hiện theo thứ tự không phải là số khi bạn liệt kê chúng sau! - thì bạn có thể thay thế %02d
bằng %d
.
Cái này hoạt động ra sao? Shell của bạn mở rộng *
thành một danh sách các tập tin trước khi nó chạy rename
lệnh. Danh sách được sắp xếp theo từ vựng (nghĩa là theo thứ tự abc) theo cài đặt ngôn ngữ hiện tại của bạn. rename
nhận tên tệp dưới dạng đối số dòng lệnh và xử lý chúng theo thứ tự chúng được liệt kê. Biểu thức ++$i
ước tính lớn hơn một giá trị hiện tại của biến $i
và cũng đặt biến $i
đó thành giá trị mới tăng. Giá trị này được chuyển đến sprintf
, định dạng nó và đặt nó bên trong văn bản khác. Văn bản này được gán trực tiếp cho biến đặc biệt $_
, chứa tên tệp. Vì các rename
tệp quy trình theo thứ tự chúng được truyền dưới dạng đối số, nên chúng được đánh số tương ứng.
Cả hai đều khai báo và tăng một biến đếm và cả hai đều sử dụng sprintf
về cơ bản giống nhau để nhúng giá trị của bộ đếm đó, được đệm bên trái bằng các số không, trong văn bản khác của tên tệp mới. (Thông tin trong một trong hai câu trả lời về cách pad với số không - và thay đổi chiều rộng padding -. Thậm chí áp dụng đồng đều cho cả hai) Lý do họ là như vậy tương tự là phương pháp trong đó câu trả lời cũ đang thực sự làm chỉ này 1 , nhưng với các bước bổ sung hữu ích cho nhiều vấn đề nhưng không thực sự cần thiết cho vấn đề này.
Để so sánh, đây là lệnh thứ hai trong câu trả lời đó trông như thế nào nếu được sửa đổi để sử dụng kiểu tôi đã sử dụng ở đây (và để tăng lên 2 chiều rộng, như tôi đã làm ở đây, thay vì 3):
rename -n 's/.+/our $i; sprintf "AS%02d.txt", ++$i/e' *
Phần giữa s/.+/
và /e
trong lệnh đó bây giờ giống như biểu thức tôi gán cho $_
(nghĩa là mã ở phía bên phải của =
toán tử) trong lệnh đầu tiên trong câu trả lời này.
s/
nhà điều hành những nỗ lực để văn bản phù hợp (tên tập tin mà vỏ của bạn mở rộng từ *
và thông qua như là đối số dòng lệnh khi nó chạy rename
) với một biểu thức chính quy , và thay thế thực hiện. /
đang được sử dụng như một dấu phân cách để phân tách các phần khác nhau của s
biểu thức. Phần đầu tiên .+
, là biểu thức chính quy; nó phù hợp với bất kỳ 1 ký tự ( .
) và thực hiện một hoặc nhiều lần ( +
) . Vì tên tệp không bao giờ trống - chúng luôn dài ít nhất một ký tự - đây là một cách để khớp với bất kỳ 1 tên tệp nào.our $i; sprintf "AS%02d.txt", ++$i
. Điều này tạo ra tên tệp mới. Thông thường, người ta sử dụng s/
để tạo văn bản là (a) thay thế văn bản chỉ khớp với một phần của tên tệp hoặc (b) dựa trên văn bản phù hợp theo một cách nào đó (ví dụ: nó có thể sử dụng một biến đặc biệt như $&
mở rộng ra trận đấu). Tuy nhiên, trong trường hợp này, văn bản phù hợp hoàn toàn không được sử dụng.our $i; sprintf "AS%02d.txt", ++$i
sẽ được sử dụng làm tên tệp, không chạy dưới dạng mã. Nhưng /e
cờ ở cuối khiến văn bản đó được coi là mã nguồn Perl và được đánh giá và sử dụng giá trị được tạo ra bằng cách đó (trong trường hợp này, giá trị trả về của sprintf
hàm dựng sẵn của Perl ) làm tên tệp mới.Mặc dù tôi nghĩ rằng phương pháp tôi đã đưa ra ở đây là một cách tiếp cận rõ ràng và đơn giản cho vấn đề này hơn bất cứ phương pháp mà sử dụng s/
với /e
, nó tốt đến mức khó nhận thức kỹ thuật mà, bởi vì nó cũng là phù hợp với một số đổi tên vấn đề tập tin khác, nơi tất cả hoặc một phần tên tệp gốc được kiểm tra và / hoặc giữ lại. Tôi đề nghị bài đăng trên blog này của Oli (người cũng đã viết câu trả lời đó ), trong đó bao gồm một số ví dụ như vậy.
1 Về mặt kỹ thuật, có là một sự khác biệt trong hành vi của các $_ =
lệnh và các s/
/e
lệnh. Trong biểu thức chính quy .+
, nó không hoàn toàn đúng .
với bất kỳ ký tự nào , vì nó không khớp với một dòng mới . Bạn rất có thể không nên sử dụng tên tệp có dòng mới trong đó, nhưng bạn có thể, và đôi khi một tệp được đặt tên theo cách đó một cách tình cờ. Nếu bạn cảm thấy thích nó, tương phản đầu ra của rename -n 'our $i; $_ = sprintf "AS%02d.txt", ++$i' $'foo\nbar'
nó rename -n 's/.+/our $i; sprintf "AS%02d.txt", ++$i/e' $'foo\nbar'
. Để .
khớp với một dòng mới, sử dụng s
cờ ở cuối (với e
). Đó là, viết /se
ở cuối thay vì /e
.
Giả sử các tệp bạn muốn đổi tên nằm trong ~/Adir
và đây là các tệp duy nhất trong thư mục này, sau đó:
n=0
for f in $( ls ~/Adir | sort ) ; do
n=$(( n+1 ))
mv -n "$f" "AS${n}.txt"
done
Kịch bản lệnh này sẽ xem xét từng tệp ~/Adir
và đổi tên thành AS1.txt, AS2.txt, ...
nếu tệp không tồn tại (sẽ không có bất kỳ ghi đè nào). Đó là lý do tại sao bạn nên đảm bảo đây là những tệp duy nhất ~/Adir
. Các sort
lệnh là chỉ trong trường hợp bạn muốn các tập tin để giữ trật tự ban đầu.
rename
là tên. Điều này có thể tốt hơn nhưng bạn có thể muốn thêm hướng dẫn cài đặt để làm cho câu trả lời này có giá trị hơn.