问题
This is a continuation of linked question.
It seems to me, that current implementation of the std/archive/tar.ts module only allows reads and writes per file and not for whole directories.
So far, my reference source are the test files, which only show case single file processing. But what if, for example, a directory ./my-dir/
with multiple files and a tar archive ./test.tar
is given.
How can I then utilize append, extract & Co. to efficiently write ./my-dir/
to ./test.tar
archive and read all file contents back from it?
回答1:
You can archive a directory by using std/fs/walk
import { walk, walkSync } from "https://deno.land/std/fs/walk.ts";
import { Tar } from "https://deno.land/std/archive/tar.ts";
// Async
const tar = new Tar();
for await (const entry of walk("./dir-to-archive")) {
if (!entry.isFile) {
continue;
}
await tar.append(entry.path, {
filePath: entry.path,
});
}
const writer = await Deno.open("./out.tar", { write: true, create: true });
await Deno.copy(tar.getReader(), writer);
Untar
implementation for folders/multiple files was broken, it was fixed by this PR and currently available in master using https://deno.land/std/archive/tar.ts
import { Untar } from "https://deno.land/std/archive/tar.ts";
import { ensureFile } from "https://deno.land/std/fs/ensure_file.ts";
import { ensureDir } from "https://deno.land/std/fs/ensure_dir.ts";
const reader = await Deno.open("./out.tar", { read: true });
const untar = new Untar(reader);
for await (const entry of untar) {
console.log(entry); // metadata
/*
fileName: "archive/deno.txt",
fileMode: 33204,
mtime: 1591657305,
uid: 0,
gid: 0,
size: 24400,
type: 'file'
*/
if (entry.type === "directory") {
await ensureDir(entry.fileName);
continue;
}
await ensureFile(entry.fileName);
const file = await Deno.open(entry.fileName, { write: true });
// <entry> is a reader
await Deno.copy(entry, file);
}
reader.close();
Update
Created a lib to allow transformations, including gzip/gunzip to create & read .tar.gz
gzip
import * as Transform from "https://deno.land/x/transform/mod.ts";
const { GzEncoder } = Transform.Transformers;
/** ... **/
const writer = await Deno.open("./out.tar.gz", { write: true, create: true });
await Transform.pipeline(tar.getReader(), new GzEncoder())
.to(writer);
writer.close();
gunzip
import * as Transform from "https://deno.land/x/transform/mod.ts";
const { GzDecoder } = Transform.Transformers;
/** ... **/
const reader = await Deno.open("./out.tar.gz", { read: true });
const untar = new Untar(
Transform.newReader(input, new GzDecoder())
);
for await (const entry of untar) {
console.log(entry);
}
来源:https://stackoverflow.com/questions/62270112/read-and-write-whole-directories-with-tar-archive-standard-library