Điều này trong cách tiếp cận tôi thường thích sử dụng.
ls | sed "s|^\(.*\)\.\([^\.]*\)$|mv \1.\2 \\`echo \1 \| md5sum \| cut -d' ' -f 1\\`.\2|" | sh -
Lệnh "ls" tạo ra một dòng các dòng văn bản. Lệnh "sed" tranforms mỗi dòng với các quy tắc khớp mẫu. Lệnh "sed" xuất ra lệnh "mv", sau đó được dẫn qua lớp vỏ "sh" để thực thi. Các tham số của lệnh "mv" giống như "mv oldfilename newfilename", đổi tên tệp. Tôi xây dựng tên tệp mới bằng lệnh sed lấy phần trước dấu chấm cuối cùng và lặp lại nó vào đầu vào của lệnh "md5sum", và sau đó chỉ lấy hàm băm từ đầu ra của nó.
Xem qua quy trình của tôi, liệt kê các tệp đầu tiên ('head -n 3' để chỉ xem 3 dòng đầu tiên):
ls | head -n 3
1000-26092016.xml
1000-27092016.xml
12312-28092016.xml
Sau đó suy nghĩ về việc chuyển đổi với sed (chưa thực hiện bất kỳ lệnh nào được tạo thông qua shell)
ls | sed "s|^\(.*\)\.\([^\.]*\)$|mv \1.\2 \1.\2|" | head -n 3
mv 1000-26092016.xml 1000-26092016.xml
mv 1000-27092016.xml 1000-27092016.xml
mv 12312-28092016.xml 12312-28092016.xml
Có ba mẫu khớp:
^\(.*\) = match from start-of-line up to a dot
\. = matches a single dot
\([^\.]*\)$ = match 0-or-more non-dot chars from end of line
Tôi muốn sử dụng sed để thay thế một tên tệp đầu vào bằng "mv filename NEWfilename", nhưng khi tôi chuyển các lệnh qua shell, tôi có thể tạo các lệnh nhận md5sum, như thế này
echo "1000-26092016" | md5sum
55b18a6b0add4a318b0079e18512b4e8 -
để chỉ lấy băm
echo "1000-26092016" | md5sum | cut -d' ' -f 1
55b18a6b0add4a318b0079e18512b4e8
Trong một vỏ unix, chúng ta có thể sử dụng các toán tử backtick (`some_command`) để chạy một lệnh phụ, ví dụ như vậy
echo "howdy date there"
howdy date there
echo "howdy `date` there"
howdy Fri Sep 15 18:39:00 IST 2017 there
Quay lại lệnh mv, tôi muốn sed tạo ra "mv here there" bằng "there" được thay thế bằng lệnh backtick để lấy md5sum. Chuỗi bên trong chuỗi thay thế sed bắt đầu như thế này
ls | sed "s|^\(.*\)\.\([^\.]*\)$|mv \1.\2 `echo \1 | md5sum | cut -d' ' -f 1`.\2|" | head -n 3
mv 1000-26092016.xml b026324c6904b2a9cb4b88d6d61c81d1.xml
mv 1000-27092016.xml b026324c6904b2a9cb4b88d6d61c81d1.xml
mv 12312-28092016.xml b026324c6904b2a9cb4b88d6d61c81d1.xml
Nhưng rõ ràng là thực hiện cùng một hàm băm cho mỗi tên tệp, vì lệnh backticky đang được chạy trước khi sed nhìn thấy chuỗi. Để dừng shell chạy lệnh backtick để sed sẽ xuất ra backticks, chúng ta phải thêm dấu gạch chéo (cũng vào ký tự ống), vì vậy một lần nữa:
ls | sed "s|^\(.*\)\.\([^\.]*\)$|mv \1.\2 \`echo \1 \| md5sum \| cut -d' ' -f 1\`.\2|" | head -n 3
mv 1000-26092016.xml `echo 1000-26092016 | md5sum | cut -d' ' -f 1`.xml
mv 1000-27092016.xml `echo 1000-27092016 | md5sum | cut -d' ' -f 1`.xml
mv 12312-28092016.xml `echo 12312-28092016 | md5sum | cut -d' ' -f 1`.xml
Đầu ra cũng cần tên tệp được trích dẫn trong trường hợp khoảng trắng, vì vậy
ls | sed "s|^\(.*\)\.\([^\.]*\)$|mv \"\1.\2\" \"\`echo \1 \| md5sum \| cut -d' ' -f 1\`.\2\"|" | grep trick
mv "a trick€€ fíle nÁme.xml" "`echo a trick€€ fíle nÁme | md5sum | cut -d' ' -f 1`.xml"
Vì vậy, hãy thử cái này bằng cách đưa nó qua một cái vỏ:
ls | sed "s|^\(.*\)\.\([^\.]*\)$|mv \"\1.\2\" \"\`echo \1 \| md5sum \| cut -d' ' -f 1\`.\2\"|" | grep trick | sh -
Nó có hoạt động không? tôi đoán:
echo "a trick€€ fíle nÁme" | md5sum
629db9c3071928ba0746f18444713b65 -
ls 629db9c3071928ba0746f18444713b65*
629db9c3071928ba0746f18444713b65.xml
Đây là một cách tiếp cận để kiểm tra chéo; sử dụng tùy chọn "ls" "-i" để xuất nút i của hệ thống tập tin unix (không thay đổi với "mv"):
ls -1i | sort -n > .before
ls | sed "s|^\(.*\)\.\([^\.]*\)$|mv \"\1.\2\" \"\`echo \1 \| md5sum \| cut -d' ' -f 1\`.\2\"|" | sh -
ls -1i | sort -n > .after
cut -d' ' -f 1 .before | while read I ; do echo "mv'd \"`grep ${I} .before`\" to \"`grep ${I} .after`\"" | sed "s| *$I *||g" ; done | head -n 3
mv'd "1000-26092016.xml" to "55b18a6b0add4a318b0079e18512b4e8.xml"
mv'd "1000-27092016.xml" to "b1baa80d99d5edf85c8aeb98185dd440.xml"
mv'd "12312-28092016.xml" to "2b2d692bd047b64c99f7b9161349d430.xml"
Hoặc, sử dụng lệnh "dán" (gói 'coreutils')
paste .before .after | head -n 3
36703389 1000-26092016.xml 36703389 55b18a6b0add4a318b0079e18512b4e8.xml
36703390 1000-27092016.xml 36703390 b1baa80d99d5edf85c8aeb98185dd440.xml
36703391 12312-28092016.xml 36703391 2b2d692bd047b64c99f7b9161349d430.xml