Dalam pendekatan ini saya sering suka menggunakan.
ls | sed "s|^\(.*\)\.\([^\.]*\)$|mv \1.\2 \\`echo \1 \| md5sum \| cut -d' ' -f 1\\`.\2|" | sh -
Perintah "ls" menghasilkan aliran baris teks. Perintah "sed" mengubah setiap baris dengan aturan pencocokan pola. Perintah "sed" menampilkan perintah "mv" yang kemudian disalurkan melalui shell "sh" untuk dieksekusi. Parameter perintah "mv" seperti "mv oldfilename newfilename", yang mengubah nama file. Saya membangun nama file baru dengan perintah sed yang mengambil bagian sebelum titik terakhir, dan menggemakannya menjadi input dari perintah "md5sum", dan kemudian hanya mengambil hash dari output itu.
Berjalan melalui proses saya, daftar file pertama ('head -n 3' untuk hanya melihat 3 baris pertama):
ls | head -n 3
1000-26092016.xml
1000-27092016.xml
12312-28092016.xml
Kemudian pikirkan tentang mentransformasikan dengan sed (belum memipakan perintah apa pun yang dihasilkan melalui 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
Ada tiga pola kecocokan:
^\(.*\) = match from start-of-line up to a dot
\. = matches a single dot
\([^\.]*\)$ = match 0-or-more non-dot chars from end of line
Saya ingin menggunakan sed untuk mengganti input nama file dengan "mv filename NEWfilename", tetapi karena saya mem-pipkan perintah melalui shell, saya dapat menghasilkan perintah yang mendapatkan md5sum, seperti ini
echo "1000-26092016" | md5sum
55b18a6b0add4a318b0079e18512b4e8 -
untuk mendapatkan hash
echo "1000-26092016" | md5sum | cut -d' ' -f 1
55b18a6b0add4a318b0079e18512b4e8
Dalam shell unix, kita dapat menggunakan operator backtick (`some_command`) untuk menjalankan sub-perintah, jadi misalnya
echo "howdy date there"
howdy date there
echo "howdy `date` there"
howdy Fri Sep 15 18:39:00 IST 2017 there
Kembali ke perintah mv, saya ingin sed untuk menghasilkan "mv di sini di sana" dengan "di sana" diganti dengan perintah backtick untuk mendapatkan md5sum. String di dalam sed-replace-string dimulai seperti ini
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
Tetapi jelas membuat hash yang sama untuk setiap nama file, karena perintah backticked dijalankan sebelum sed melihat string. Untuk menghentikan shell yang menjalankan perintah backtick sehingga sed akan menampilkan backtick, kita harus menambahkan dulu slash (juga ke karakter pipa), jadi sekali lagi:
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
Outputnya juga perlu nama file untuk dikutip dalam kasus spasi, jadi
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"
Jadi mari kita coba yang ini, dengan menyalurkannya melalui shell:
ls | sed "s|^\(.*\)\.\([^\.]*\)$|mv \"\1.\2\" \"\`echo \1 \| md5sum \| cut -d' ' -f 1\`.\2\"|" | grep trick | sh -
Apa itu bekerja ? saya tebak:
echo "a trick€€ fíle nÁme" | md5sum
629db9c3071928ba0746f18444713b65 -
ls 629db9c3071928ba0746f18444713b65*
629db9c3071928ba0746f18444713b65.xml
Berikut ini adalah pendekatan untuk cross-check; gunakan opsi "ls" "-i" untuk menampilkan simpul-sistem file unix (yang tidak berubah dengan "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"
Atau, menggunakan perintah "tempel" (paket '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