Skip to content

Commit

Permalink
Feat: package_ibooks_epub: assign source/dest via args, add README
Browse files Browse the repository at this point in the history
  • Loading branch information
ezirmusitua committed Sep 13, 2023
1 parent cf5af78 commit 6186ee0
Show file tree
Hide file tree
Showing 2 changed files with 32 additions and 17 deletions.
16 changes: 16 additions & 0 deletions package_ibooks_epub/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
## 打包 iBooks 中的 epub 图书文件

一个用于重新打包 iBooks 中的 epub 图书文件的工具。

场景:
epub 图书在导入到 iBooks 之后,会被解压并添加 plist 文件。
如果使用 calibre 导入 iBooks 中的 epub 文件夹,会显示为文件夹而无法导入。
使用此工具能够将 iBooks 中的 epub 文件夹重新打包为可被 calibre 读取的 epub 文件。

用法:

```bash
./package_ibooks_epub <存储了 iBooks 图书文件的目录> <重新打包后保存的目录>
# 比如下面的指令能将 iBooks 书库中的图书重新打包并保存到“下载”目录中
./package_ibooks_epub /Users/${USER}/Library/Mobile\ Documents/iCloud\~com\~apple\~iBooks/Documents/ /Users/${USER}/Downloads
```
33 changes: 16 additions & 17 deletions package_ibooks_epub/src/main.rs
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
use std::env;
use std::fs::{self, DirEntry, File};
use std::io::Write;
use std::path::Path;
Expand All @@ -7,7 +8,7 @@ use zip::write::FileOptions;
fn read_dir(path: &Path, predicate: fn(&DirEntry) -> bool) -> Result<Vec<DirEntry>, String> {
let filename = path.file_name().unwrap().to_str().unwrap();
if !path.is_dir() {
return Err(format!("{} not a directory", filename).to_string());
return Err(format!("{} 不是文件夹", filename).to_string());
}
let entries = match fs::read_dir(path) {
Ok(e) => e,
Expand All @@ -32,8 +33,8 @@ fn ends_with_epub(entry: &DirEntry) -> bool {
fn copy_original(from: &Path, to: &Path) {
let filename = from.file_name().unwrap().to_str();
match fs::copy(from, to) {
Ok(_) => println!("{} was copied", &filename.unwrap()),
Err(e) => println!("Error while copy: {}", e),
Ok(_) => println!("《{}》已复制", &filename.unwrap()),
Err(e) => println!("复制错误: {}", e),
};
}

Expand Down Expand Up @@ -64,7 +65,6 @@ fn write_zip_directory(
path: &Path,
folder: &str,
) -> Result<(), Box<dyn std::error::Error>> {
println!("write zip directory {}", path.display());
let options = FileOptions::default()
.compression_method(zip::CompressionMethod::Stored)
.unix_permissions(0o755);
Expand All @@ -81,7 +81,6 @@ fn write_zip_directory(
prefix
}
};
println!("writing prefix, {}", prefix);
let subs = read_dir(path, |_| true)?;
for sub in subs {
if sub.path().is_dir() {
Expand All @@ -94,11 +93,6 @@ fn write_zip_directory(
}

fn create_zip_archive(source: &Path, dest: &Path) -> Result<(), Box<dyn std::error::Error>> {
println!(
"create zip archive {} -> {}",
source.display(),
dest.display()
);
let file = File::create(dest)?;
let mut zip = zip::ZipWriter::new(file);
write_zip_directory(&mut zip, source, "")?;
Expand All @@ -107,23 +101,28 @@ fn create_zip_archive(source: &Path, dest: &Path) -> Result<(), Box<dyn std::err
}

fn main() {
let source = Path::new("books");
let dest = Path::new("packaged");
let args: Vec<String> = env::args().collect();
if args.len() != 3 {
println!("用法: {} <source> <dest>, source 为 iBooks 中的 epub 文件,dest 为重新打包后保存的位置", args[0]);
exit(-1);
}
let source = Path::new(&args[1]);
let dest = Path::new(&args[2]);
let entries = match read_dir(source, ends_with_epub) {
Ok(v) => v,
Err(e) => {
println!("Error: {}", e);
println!("错误: {}", e);
exit(-1);
}
};
for entry in entries {
let filetype = entry.file_type().unwrap();
let filename = entry.file_name();
if filetype.is_dir() {
match create_zip_archive(&entry.path(), &dest.join(filename)) {
Ok(_) => (),
Err(e) => println!("Error: {}", e),
}
match create_zip_archive(&entry.path(), &dest.join(&filename)) {
Ok(_) => println!("《{}》已打包", &filename.to_str().unwrap()),
Err(e) => println!("错误: {}", e),
};
} else {
copy_original(&entry.path(), &dest.join(filename));
}
Expand Down

0 comments on commit 6186ee0

Please sign in to comment.