Artikel:Berbagai trik rename di command line
Untuk berdiskusi dengan sesama programer dan peminat
PHP, bergabunglah dengan milis id-php,
milis PHP Indonesia paling aktif sejak 2002. Untuk subscribe,
kunjungi halaman web milis atau kirimkan email kosong ke id-php-subscribe@yahoogroups.com.
|
[draft artikel infolinux]
Pendahuluan
Rename, atau mengganti nama file, adalah pekerjaan yang sering sekali
harus kita lakukan. Saat ingin mereorganisasi dokumen-dokumen kita,
seringkali kita harus mengubah lokasi direktori dan nama-nama
file. Kadang-kadang sebuah program memberi nama otomatis pada sebuah
file dan harus kita ganti. Dan, saat bertukar file dengan rekan atau
mendownload dari Internet, seringkali nama filenya tidak cocok dengan
selera kita.
Mengganti nama file lewat command line sampai saat ini tetap dapat
menjadi salah satu pilihan favorit bagi Anda ketimbang lewat GUI,
karena fleksibilitas dan programabilitasnya tak terkalahkan. Artikel
ini ingin mendemokan mengapa demikian halnya, lewat contoh berbagai
trik rename di command line dari dasar hingga lanjut.
Shell
Sintaks dasar perintah mv
Perintah dasar di shell untuk mengganti nama (dan/atau memindahkan)
file adalah mv (singkatan dari move). Perintah ini dapat
mengganti nama file menjadi nama lain dan/atau lokasi lain jika diberi
2 argumen:
$ mv NAMA1 NAMA2
$ mv NAMA1 LOKASI-LAIN/NAMA1
Perhatian: jika NAMA2 adalah sebuah file yang sudah ada, maka file
tersebut akan tertimpa isinya.
Jika diberi lebih dari 2 argumen, maka argumen terakhir haruslah
sebuah direktori tujuan (bukan file), dan efeknya adalah memindahkan
file/direktori ke direktori tujuan tersebut. contoh:
$ mv FILE1 FILE2 FILE3 DIR1 DIR2 DIR-TUJUAN
Beberapa opsi perintah mv yang sering digunakan adalah -i
(interactive) yang akan mengeluarkan pertanyaan konfirmasi untuk
setiap file/direktori yang akan dipindahkan, dan -v
(verbose) yang akan menampilkan setiap file/direktori yang sedang
dipindahkan.
Mengganti nama file yang aneh
Untuk mengganti nama file yang aneh di command line, seperti biasa
kita menggunakan fitur escaping dari shell. Misalnya, untuk nama
file yang mengandung spasi kita dapat menggunakan kutip tunggal (')
atau kutip ganda (") atau meng-escape spasi dengan backslash
(\). Contoh:
$ mv 'Aku cinta padamu.txt' "Mimpi di Jum'at siang.txt" lirik/
$ mv lirik/Aku\ cinta\ padamu.txt lirik/aku_cinta_padamu.txt
Catatan: Anda dapat menggunakan fasilitas tab completion sehingga
shell otomatis akan menuliskan nama file lengkap, lengkap dengan
escapingnya. Misalnya:
$ mv Aku<TAB>
Saat Anda menekan tombol Tab, maka otomatis shell akan menambahkan
sehingga menjadi:
$ mv Aku\ cinta\ padamu.txt
Perbedaan kutip tunggal dan ganda adalah, di dalam kutip ganda
substitusi variabel dan backtick masih berfungsi, contoh:
$ ls -1 hasil*
hasil tes 1.txt
hasil tes 2.txt
$ mv hasil\ tes\ 1.txt "hasil tes 1 - `date +%Y-%m-%d`".txt
$ mv hasil\ tes\ 2.txt 'hasil tes 2 - `date +%Y-%m-%d`'.txt
$ ls hasil*
hasil tes 1 - 2008-07-07.txt
hasil tes 2 - `date +%Y-%m-%d`.txt
Jika di dalam kutip ada kutip lagi, Anda dapat menggunakan backslash,
kutip luar yang berbeda (seperti contoh sebelumnya), atau keluar dulu
dari kutip dan menggunakan kutip yang berbeda:
$ mv Mimpi\ di\ Jum\'at\ siang.txt mimpi_di_jumat_siang.txt
$ mv "Mimpi di Jum'at siang.txt" mimpi_di_jumat_siang.txt
$ mv mimpi_di_jumat_siang.txt 'Mimpi di Jum'"'"'at siang.txt'
Perhatikan contoh terakhir. Untuk menulis kutip tunggal pada kata
Jum'at, kita keluar dulu dari kutip tunggal sebelumnya, lalu
menggunakan kutip ganda (") untuk mengutip si kutip tunggal. Hasilnya
memang agak sulit dibaca, tapi jenis kutip seperti ini kadang-kadang
diperlukan.
Mengganti nama banyak file sekaligus
Misalnya kita ingin mengganti beberapa file yang tidak memiliki
akhiran menjadi *.txt.
$ ls -1
1
2
13
40
Tujuan kita:
1.txt
2.txt
13.txt
40.txt
Seorang pemula mungkin akan langsung berpikiran:
$ mv * *.txt
Sayangnya, ini tidak bekerja karena wildcard * oleh shell akan
diekspansi sehingga menjadi:
$ mv 1 2 13 40 *.txt
Seperti telah disebutkan sebelumnya, jika argumen perintah mv lebih
dari 2 maka argumen terakhir haruslah direktori. Dengan demikian mv
tidak mendukung penggantian banyak nama file sekaligus. Kita harus
menggunakan looping di shell:
$ for f in *;do mv "$f" "$f".txt; done
Perhatikan kutip "" di atas, ini untuk menginstruksikan shell agar
mengutip hasil ekspansi agar jika ditemukan file bernama aneh di
variabel f (seperti spasi, kutip, dsb) tidak akan mengacaukan
perintah mv.
Untuk melakukan penggantian selektif, kita tinggal menyesuaikan
wildcard-nya saja. Misalnya, untuk hanya memroses file yang namanya
terdiri dua huruf dan bukan satu:
$ for f in ??; do ...; done
Menukar 2 nama file
Menukar (swapping) dua nama file juga sesuatu yang sering perlu
dilakukan. Umumnya algoritmanya adalah dengan melibatkan file
sementara sbb:
$ mv FILE1 SEMENTARA
$ mv FILE2 FILE1
$ mv SEMENTARA FILE2
Sehingga efeknya adalah FILE1 menjadi FILE2 dan sebaliknya. Trik
intinya adalah menghasilkan nama acak/sementara SEMENTARA yang tidak
bentrok dengan file yang sudah ada. Untuk ini kita dapat menggunakan
bantuan perintah tempfile:
$ temp=`tempfile --directory=.`; \
mv FILE1 $temp && mv FILE2 FILE1 && mv $temp FILE2
Catatan: kita menggunakan && agar jika terjadi kegagalan di satu step
kita bisa langsung berhenti. Misalnya jika kita gagal mengubah FILE1
menjadi $temp, kita tidak mengganti FILE2 menjadi FILE1 sehingga
berefek FILE1 tertimpa oleh FILE2.
Tip: Anda dapat membuat skrip sederhana seperti ini:
#!/bin/bash
if test $# -ne 2; then echo "Usage: $0 FILE1 FILE2"; exit 1; fi
temp=`tempfile --directory=.`
mv "$1" $temp && mv "$2" "$1" && mv $temp "$2"
lalu Anda beri nama misalnya tukar, sehingga di lain waktu Anda
tidak perlu mengingat perintah rumit lagi melainkan hanya:
$ tukar FILE1 FILE2
Substitusi di nama file
Untuk mengganti nama file *.MP3 (huruf kapital) menjadi *.mp3 (huruf
kecil), Anda dapat menggunakan sintaks seperti ini:
$ ls -1
satu.MP3
2.MP3
satu lagi.MP3
$ for f in *.MP3; do mv "$f" "${f/.MP3/.mp3}"; done
$ ls -1
satu.mp3
2.mp3
satu lagi.mp3
Sintaks bash:
${var/.../...}
akan melakukan substitusi pada variabel var yaitu mencari string
dan diganti dengan string kedua. Detil mengenai sintaks ini dan
beberapa sintaks ${...} lainnya dapat dibaca di manual bash (man
bash).
Contoh yang lebih kompleks dengan shell
Tentu saja, Anda dapat menggunakan segala macam konstruksi shell yang
tersedia dalam mengganti nama file. Misalnya, Anda ingin
mereorganisasi file-file ke dalam direktori dengan awalan huruf
pertamanya. Anda juga ingin mengkonversinya ke dalam huruf kecil
semua. Tapi Anda tidak ingin mengganggu direktori. Yaitu:
0/
a/
b/
c/
...
z/
Aku cinta padamu.mp3
Tiren - cd1of2.avi
Tiren - cd2of2.avi
9 and a half weeks.MPG
menjadi:
0/9 and a half weeks.mpg
a/aku cinta padamu.mp3
t/tiren - cd1of2.avi
t/tiren - cd2of2.avi
...
Perintahnya:
$ for f in *;do
if test -f "$f"; then
hurufkecil="`echo "$f" | tr A-Z a-z`"
hurufawal="${hurufkecil:0:1}"
if test '!' -d "$hurufawal"; then hurufawal=0; fi
mv -v "$f" "$hurufawal/$hurufkecil"
fi
done
Dalam contoh di atas, selain looping (for), digunakan juga kondisi
(if), pengecekan file (test), perintah tr, dan penggunaan
variabel.
perlrename dan phprename
Pekerjaan yang semakin kompleks dan high level membutuhkan tool
yang lebih kompleks dan high level pula. Sehari-hari, kecuali
untuk pekerjaan mengganti nama yang paling sederhana, saya tidak lagi
menggunakan perintah mv lagi melainkan menggunakan skrip
perlrename. Bagi pembaca yang hanya familiar dengan PHP, saya
membuatkan juga versi PHP-nya, phprename. Listing phprename
dapat dilihat di Listing 1, untuk perlrename dapat didownload di
website saya. Tentu saja Anda pun bebas membuat pythonrename,
rubyrename, shellrename, dst.
[Listing 1]
Prinsip kerja dari skrip ini adalah, Anda cukup menyuplai sebuah kode
kecil dalam bahasa Perl (atau PHP, ...) yang mengubah satu variabel
(di perlrename, $_ sementara di phprename $file). Variabel
ini akan diisi dengan setiap nama file/direktori yang ingin
diganti. Proses penggantian nama file, pengecekan penimpaan,
pemrosesan rekursif, dsb akan dilakukan oleh skrip. Sehingga, Anda
cukup berfokus pada proses inti yaitu penggantian nama file itu
sendiri.
Keunggulan menggunakan skrip ini dibandingkan mv langsung adalah:
- lebih mudah/sederhana, cukup mengubah nilai variabel;
- dapat memanfaatkan seluruh fasilitas bahasa pemrograman yang umumnya lebih ekspresif dan bertenaga dibandingkan shell;
- ada mode rekursif (opsi -r);
- ada mode tes (opsi -d) untuk hanya mengetes dan tidak benar-benar melakukan penggantian nama file;
- untuk menghindari penimpaan, otomatis menambahkan akhiran .1, .2, dsb (kecuali jika diinstruksikan menimpa dengan opsi o);
- ada opsi (-f) untuk tidak mengacuhkan direktori;
Beberapa contoh sederhana
Mari lihat beberapa contoh sederhana penggunaan skrip ini. Kedua versi
PHP dan Perl diberikan, silakan pilih salah satu. Tip: biasakan
tambahkan dulu opsi -d untuk melakukan pengetesan, tidak betul-betul
mengubah nama file. Jika hasilnya sudah terlihat betul, barulah
hilangkan opsi -d.
Untuk mengganti semua file menjadi huruf kecil semua (umumnya sering
harus dilakukan jika kita mengambil file dari DOS/CDROM/FTP server):
$ perlrename -e'$_ = lc' *
$ phprename -e'$file = strtolower($file);' *
Untuk mengganti semua file *.DAT menjadi *.mpg:
$ perlrename -e's/\.DAT$/.mpg/' *
$ phprename -e'$file = preg_replace("/\.DAT\$/", ".mpg", $file);' *
Contoh sebelumnya di shell (memindahkan file ke direktori sesuai nama
awal filenya):
$ perlrename -fe'$_ = lc; ($hurufawal)=/(.)/;
$hurufawal !~ /[a-z]/ && $hurufawal="0";
$_ = "$hurufawal/$_"' *
$ phprename -fe'$file = strtolower($file);
$hurufawal = substr($file, 0, 1);
if ($hurufawal < "a" || $hurufawal > "z") $hurufawal = "0";
$file = "$hurufawal/$file";' *
Mengacak nama file
Kadang-kadang diperlukan jika Anda ingin memroses beberapa file tapi
ingin urutannya diacak (tidak alfabetis) dan Anda tidak peduli nama
filenya apa:
$ perlrename -de'$_ = rand' *
$ phprename -de'$file = md5($file);' *
Menyandikan nama file dengan uuencode atau mcrypt, iseng:
$ phprename -de'$file = preg_replace("#/#", "@",
base64_encode($file));' *
Catatan: enkoding base64 menghasilkan "/" yang merupakan pemisah path
di Unix sehingga harus kita ganti misalnya dengan '@'.
Mengubah nama file menjadi angka
Kadang kita ingin mengubah banyak file menjadi nomor saja, dengan
akhiran tetap (mis: satu.txt menjadi 0001.txt, dst).
$ perlrename -e '$i||=0; $i++ unless $TESTING;
/.+\.(.+)/; $ext=$1;
$ndig = @ARGV >= 1000 ? 4 : @ARGV >= 100 ? 3 : @ARGV >= 10 ? 2 : 1;
$_ = sprintf "%0${ndig}d%s", $i, (defined($ext) ? ".$ext" : "");' *
$ phprename -e'global $i, $args;
preg_match("/.+\.(.+)/", $file, $m);
if (!$TESTING) $i++;
$ndig = count($args) >= 1000 ? 4 : (count($args) >= 100 ? 3 :
(count($args) >= 10 ? 2 : 1));
$file = sprintf("%0{$ndig}d%s", $i, isset($m[1]) ? ".$m[1]" : "");' *
Memindahkan semua file ke direktori yang aktif
Skrip ini memindahkan semua file yang ada di subdirektori ke dalam
direktori saat ini, berguna jika kita ingin mengumpulkan file yang
tersebar di banyak subdirektori dan pegal jika harus dipindahkan satu
persatu secara manual:
$ perlrename -dre'BEGIN {use Cwd; $cwd=getcwd if $TESTING}
$_="$cwd/$_" if -f' *
$ phprename -dre'global $i, $cwd;
if ($i++ == 0) { if ($TESTING) $cwd = getcwd(); }
if (is_file($file)) $file = "$cwd/$file";' *
Hasilnya:
1/1a.txt
1/2/2a.txt
1/2/2b.txt
1/1b.txt
1/sama.txt
3.txt
sama.txt
menjadi:
1a.txt
1b.txt
2a.txt
3.txt
sama.txt
sama.txt.1
Penggunaan variabel global dan kode if ($i++ == 0) di PHP, dan
blok BEGIN {} di Perl di atas berguna agar kode yang diapitnya hanya
dijalankan sekali saja (mis: untuk inisialisasi saja), tidak untuk
setiap file yang akan diproses.
Menambah informasi ukuran file ke nama file
$ perlrename -de'
($name, $ext) = /(.+)\.(.+)/;
$_ = "$name (".(-s)." byte).$ext" *
Hasilnya:
notes.txt
dua.mp3
akan menjadi:
notes (268 byte).txt
dua (2392423 byte).mp3
Membersihkan nama file hasil download
Nama file hasil download, terutama dari jaringan P2P, kadang-kadang
aneh atau macam-macam. Kita dapat melakukan pembersihan misalnya
mengubah semua yang di luar [A-Za-z0-9_-] menjadi .:
$ phprename -de'$file = preg_replace("/[^A-Za-z0-9_-]+/", ".", $file);' *
Hasilnya:
Aku cinta padamu.mp3
[BARU] Wall-E (2008).avi
menjadi:
Aku.cinta.padamu.mp3
.BARU.Wall-E.2008.avi
Nama file sederhana seperti ini lebih mudah diketik dan tidak perlu
dikutip/diescape, karenanya cukup popular dipakai orang.
Menghilangkan aksen. Nama-nama hasil download file dari Eropa
misalnya Prancis, Jerman, dsb kadang juga mengandung karakter
aksen/diakritik dan kadang agak bermasalah dalam ditangani. Untuk
menghilangkannya:
$ perlrename -de'use Text::Unaccent; $_=unac_string("utf8", $_);
s/[^A-za-z0-9_-]/./g;' *
Hasilnya:
Céline Dion - Ce N'était Qu'un Rêve.mp3
Menjadi:
Celine Dion - Ce N'etait Qu'un Reve.mp3
Catatan: Skrip di atas membutuhkan modul Perl Text::Unaccent, yang
dapat diinstal dengan cpan. tersedia juga program open source
bernama detox untuk melakukan ini.
Karakter Mandarin. Mendownload file dengan karakter China juga
kadang bermasalah. Kita dapat mengkonversinya menjadi latin, yaitu
aksara pinyinnya:
perlrename -de'use Lingua::Han::PinYin; $h||=Lingua::Han::PinYin->new;
$_=$h->han2pinyin($_)' *
Contoh hasilnya:
liudehua - zhongguoren.mp3
Catatan: membutuhkan modul Perl Lingua::Han::PinYin.
Mengganti nama file multimedia
File musik dan video cukup sering harus kita ganti namanya, karena
memang file-file itu yang paling sering didownload atau
disharing. Untuk file musik saya juga membuat skrip yang sedikit lebih
high-level yaitu perlmp3tag. Konsepnya mirip perlrename, tapi
untuk setiap file skrip akan menyediakan juga metadata di
variabel-variabel: $TITLE, $TRACK, $ARTIST, $ALBUM, $COMMENT, $YEAR,
$GENRE. Sementara nama filenya sendiri di $FILE. Anda cukup menyuplai
kode Perl untuk mengganti isi variabel $FILE (atau $TITLE, dsb).
Misalnya, untuk mengganti nama file musik menjadi berformat "ARTIST -
ALBUM - TRACK - JUDUL.mp3":
$ perlmp3tag -e'$FILE = sprintf("%s - %s - %02d - %s.mp3",
$ARTIST, $ALBUM, $TRACK, $TITLE)' *.mp3
Untuk mengganti tahun menjadi 2008 dan nama artis menjadi huruf kecil
semua:
$ perlmp3tag -e'$YEAR = 2008; $ARTIST = lc($ARTIST)' *.mp3
Tentu saja, banyak aplikasi pemutar multimedia (termasuk Amarok, JuK)
menyediakan fasilitas penggantian nama file musik secara masal, namun
fleksibilitas yang kita peroleh lewat skrip lebih banyak.
Penutup
perlrename, phprename, perlmp3tag dapat didownload di:
http://people.masterweb.net/steven/files/.
Pertanyaan atau komentar dapat dilayangkan ke penulis di
<steven@masterweb.net>.
Untuk berdiskusi dengan sesama programer dan peminat
PHP, bergabunglah dengan milis id-php,
milis PHP Indonesia paling aktif sejak 2002. Untuk subscribe,
kunjungi halaman web milis atau kirimkan email kosong ke id-php-subscribe@yahoogroups.com.
|
|