split Command untuk DOS / Windows Via Groovy

Salah satu perintah yang paling saya rindukan dari Linux saat bekerja di lingkungan Windows / DOS adalah perintah split. Perintah yang sangat berguna ini memungkinkan seseorang untuk membagi file besar menjadi beberapa file kecil yang ditentukan oleh spesifikasi baik berdasarkan jumlah baris atau jumlah byte (atau kilobyte atau megabyte) yang diinginkan untuk file yang lebih kecil. Ada banyak kegunaan untuk fungsionalitas tersebut termasuk menyesuaikan file ke media tertentu, membuat file "dapat dibaca" oleh aplikasi dengan batasan panjang file, dan sebagainya. Sayangnya, saya tidak mengetahui perpecahan yang setara untuk Windows atau DOS. PowerShell dapat dibuat skrip untuk melakukan sesuatu seperti ini, tetapi implementasi itu khusus untuk PowerShell. Tersedia juga produk pihak ketiga yang menjalankan fungsi serupa. Namun,solusi yang ada ini meninggalkan cukup untuk diinginkan sehingga saya memiliki motivasi untuk menerapkan setara perpecahan di Groovy dan itu adalah subjek posting ini. Karena Groovy berjalan di JVM, implementasi ini secara teoritis dapat dijalankan di sistem operasi apa pun dengan implementasi Java Virtual Machine modern.

Untuk menguji dan mendemonstrasikan skrip split berbasis Groovy, diperlukan beberapa jenis file sumber. Saya akan menggunakan Groovy untuk membuat file sumber ini dengan mudah. Skrip Groovy sederhana berikut, buildFileToSplit.groovy, membuat file teks sederhana yang dapat dipisahkan.

#!/usr/bin/env groovy // // buildFileToSplit.groovy // // Accepts single argument for number of lines to be written to generated file. // If no number of lines is specified, uses default of 100,000 lines. // if (!args) { println "\n\nUsage: buildFileToSplit.groovy fileName lineCount\n" println "where fileName is name of file to be generated and lineCount is the" println "number of lines to be placed in the generated file." System.exit(-1) } fileName = args[0] numberOfLines = args.length > 1 ? args[1] as Integer : 100000 file = new File(fileName) // erases output file if it already existed file.delete() 1.upto(numberOfLines, {file << "This is line #${it}.\n"}) 

Skrip sederhana ini menggunakan pegangan "args" yang tersedia secara implisit dari Groovy untuk mengakses argumen baris perintah untuk skrip buildFileToSplit.groovy. Ini kemudian membuat satu file dengan ukuran berdasarkan jumlah baris argumen yang diberikan. Setiap baris sebagian besar tidak orisinal dan menyatakan "Ini adalah baris #" diikuti dengan nomor baris. Ini bukan file sumber yang bagus, tetapi berfungsi untuk contoh pemisahan. Cuplikan layar berikutnya menunjukkan itu berjalan dan outputnya.

File source.txt yang dihasilkan terlihat seperti ini (hanya awal dan akhir yang ditampilkan di sini):

This is line #1. This is line #2. This is line #3. This is line #4. This is line #5. This is line #6. This is line #7. This is line #8. This is line #9. This is line #10. . . . This is line #239. This is line #240. This is line #241. This is line #242. This is line #243. This is line #244. This is line #245. This is line #246. This is line #247. This is line #248. This is line #249. This is line #250. 

Sekarang ada file sumber yang tersedia untuk dibagi. Skrip ini secara signifikan lebih panjang karena saya telah membuatnya memeriksa lebih banyak kondisi kesalahan, karena ia perlu menangani lebih banyak parameter baris perintah, dan hanya karena ia melakukan lebih dari skrip yang menghasilkan file sumber. Skrip, cukup disebut split.groovy, ditampilkan berikut:

#!/usr/bin/env groovy // // split.groovy // // Split single file into multiple files similarly to how Unix/Linux split // command works. This version of the script is intended for text files only. // // This script does differ from the Linux/Unix variant in certain ways. For // example, this script's output messages differ in several cases and this // script requires that the name of the file being split is provided as a // command-line argument rather than providing the option to provide it as // standard input. This script also provides a "-v" ("--version") option not // advertised for the Linux/Unix version. // // CAUTION: This script is intended only as an illustration of using Groovy to // emulate the Unix/Linux script command. It is not intended for production // use as-is. This script is designed to make back-up copies of files generated // from the splitting of a single source file, but only one back-up version is // created and is overridden by any further requests. // // //marxsoftware.blogspot.com/ // import java.text.NumberFormat NEW_LINE = System.getProperty("line.separator") // // Use Groovy's CliBuilder for command-line argument processing // def cli = new CliBuilder(usage: 'split [OPTION] [INPUT [PREFIX]]') cli.with { h(longOpt: 'help', 'Usage Information') a(longOpt: 'suffix-length', type: Number, 'Use suffixes of length N (default is 2)', args: 1) b(longOpt: 'bytes', type: Number, 'Size of each output file in bytes', args: 1) l(longOpt: 'lines', type: Number, 'Number of lines per output file', args: 1) t(longOpt: 'verbose', 'Print diagnostic to standard error just before each output file is opened', args: 0) v(longOpt: 'version', 'Output version and exit', args: 0) } def opt = cli.parse(args) if (!opt || opt.h) {cli.usage(); return} if (opt.v) {println "Version 0.1 (July 2010)"; return} if (!opt.b && !opt.l) { println "Specify length of split files with either number of bytes or number of lines" cli.usage() return } if (opt.a && !opt.a.isNumber()) {println "Suffix length must be a number"; cli.usage(); return} if (opt.b && !opt.b.isNumber()) {println "Files size in bytes must be a number"; cli.usage(); return} if (opt.l && !opt.l.isNumber()) {println "Lines number must be a number"; cli.usage(); return} // // Determine whether split files will be sized by number of lines or number of bytes // private enum LINES_OR_BYTES_ENUM { BYTES, LINES } bytesOrLines = LINES_OR_BYTES_ENUM.LINES def suffixLength = opt.a ? opt.a.toBigInteger() : 2 if (suffixLength  1 ? opt.arguments()[1] : "x" try { file = new File(filename) if (!file.exists()) { println "Source file ${filename} is not a valid source file." System.exit(-4) } int fileCounter = 1 firstFileName = "${prefix}${fileSuffixFormat.format(0)}" if (verboseMode) { System.err.println "Creating file ${firstFileName}..." } outFile = createFile(firstFileName) if (bytesOrLines == LINES_OR_BYTES_ENUM.BYTES) { int byteCounter = 0 file.eachByte { if (byteCounter < numberBytes) { outFile << new String(it) } else { nextOutputFileName = "${prefix}${fileSuffixFormat.format(fileCounter)}" if (verboseMode) { System.err.println "Creating file ${nextOutputFileName}..." } outFile = createFile(nextOutputFileName) outFile << new String(it) fileCounter++ byteCounter = 0 } byteCounter++ } } else { int lineCounter = 0 file.eachLine { if (lineCounter < numberLines) { outFile << it << NEW_LINE } else { nextOutputFileName = "${prefix}${fileSuffixFormat.format(fileCounter)}" if (verboseMode) { System.err.println "Creating file ${nextOutputFileName}..." } outFile = createFile(nextOutputFileName) outFile << it << NEW_LINE fileCounter++ lineCounter = 0 } lineCounter++ } } } catch (FileNotFoundException fnfEx) { println System.properties println "${fileName} is not a valid source file: ${fnfEx.toString()}" System.exit(-3) } catch (NullPointerException npe) { println "NullPointerException encountered: ${npe.toString()}" System.exit(-4) } /** * Create a file with the provided file name. * * @param fileName Name of file to be created. * @return File created with the provided name; null if provided name is null or * empty. */ def File createFile(String fileName) { if (!fileName) { println "Cannot create a file from a null or empty filename." return null } outFile = new File(fileName) if (outFile.exists()) { outFile.renameTo(new File(fileName + ".bak")) outFile = new File(fileName) } return outFile } 

Skrip ini dapat dioptimalkan dan dimodulasi dengan lebih baik, tetapi ini memenuhi tujuannya untuk mendemonstrasikan bagaimana Groovy menyediakan pendekatan yang bagus untuk mengimplementasikan skrip utilitas yang tidak bergantung platform.

Cuplikan layar berikutnya menunjukkan penggunaan skrip dari dukungan CLI bawaan Groovy.

Dua snapshot layar berikutnya mendemonstrasikan pemisahan file sumber menjadi file yang lebih kecil dengan nomor baris dan byte masing-masing (dan menggunakan sufiks dan opsi nama file yang berbeda). Gambar pertama menunjukkan bahwa tiga file keluaran dihasilkan ketika dibagi menjadi 100 baris (250 baris dalam file sumber). Opsi -a menentukan bahwa empat tempat bilangan bulat akan ada di nama file. Berbeda dengan pemisahan Linux, skrip ini tidak menjamin bahwa jumlah bilangan bulat yang diberikan pengguna cukup untuk menutupi jumlah file keluaran yang diperlukan.

Gambar kedua (gambar berikutnya) menunjukkan skrip yang membagi file sumber berdasarkan jumlah byte dan menggunakan nama file yang berbeda dan hanya dua bilangan bulat untuk penomoran.

Seperti disebutkan di atas, skrip ini adalah "potongan kasar". Ini dapat ditingkatkan dalam hal kode itu sendiri serta dalam hal fungsionalitas (diperpanjang untuk mendukung format biner yang lebih baik dan untuk memastikan sufiks nama file cukup panjang untuk jumlah file keluaran). Namun, skrip di sini menunjukkan salah satu penggunaan favorit saya dari Groovy: untuk menulis skrip yang tidak bergantung platform menggunakan pustaka Java dan Groovy yang sudah dikenal (SDK dan GDK).

Cerita ini, "Perintah terpisah untuk DOS / Windows Via Groovy" pada awalnya diterbitkan oleh JavaWorld.