Sort files into collections, e.g. music or documents.
npm install create-file-collections
create-file-collections
lets you sort files in a directory into collections of links. Consider the following music files:
src/
foo.mp3
bar.mp3
baz.mp3
We want to sort them into collections of symlinks.
albums/
Hey/
a.mp3 -> ../../src/foo.mp3
c.mp3 -> ../../src/baz.mp3
Ho/
b.mp3 -> ../../src/bar.mp3
years/
2004/
a.mp3 -> ../../src/foo.mp3
b.mp3 -> ../../src/bar.mp3
2006/
c.mp3 -> ../../src/baz.mp3
Let's define a function computeLinks
that computes the collections a file belongs to. For the sake of simplicity, I shortened the ID3 tag parsing code.
const computeLinks = (file, cb) => {
readID3Tags(file.path, (err, tags) => {
if (err) return cb(err)
const links = []
for (let tag in tags) {
const value = tags[tag]
links.push([tag, value, file.basename])
}
cb(null, links)
})
}
Because create-file-collections
is agnostic about where and how to store links, we need to provide two functions put
(to create them) and del
(to delete them).
This is a simplified implementation for creating symlinks:
const fs = require('fs')
const put = (link, target, cb) => {
fs.access(link, fs.constants.R_OK, (err) => {
if (err && err.code === 'ENOENT') {
fs.symlink(target, link, cb)
} else cb()
})
}
const del = (link, target, cb) => {
fs.unlink(link, cb)
}
Now, to run the sorting process, pass everything into createCollections
. It returns a readable stream, so we can listen to data
events.
createCollections(dir, computeLinks, put, del)
.on('error', console.error)
.on('data', (file) => {
console.log(file.relative, file.links)
})
To speed up the sorting process, create-file-collections
will add all files and their links to an object. It looks like this:
{
'foo.mp3': [
['albums', 'Hey', 'a.mp3'],
['years', '2004', 'a.mp3']
],
'bar.mp3': [
['albums', 'Ho', 'b.mp3'],
['years', '2004', 'b.mp3']
],
'baz.mp3': [
['albums', 'Hey', 'c.mp3'],
['years', '2006', 'c.mp3']
]
}
If you provide this object when calling createCollections
again, it will only tell you to create and delete the necessary links:
const oldTree = {…} // retrieve the last tree somehow
createCollections('path/to/src/dir', computeLinks, put, del, {
oldTree: oldTree,
saveTree: (newTree) => {
// store the new tree somehow
}
})
createCollections('path/to/src/dir', computeLinks, put, del, opt = {})
Returns a readable stream in object mode, emitting vinyl file objects.
dir
- must be a valid directory
computeLinks(file, cb)
file
is avinyl
object- must call
cb
with a list of links
put(link, target, cb)
- must create a link from
link
totarget
- must create a link from
del(link, target, cb)
- must delete a link from
link
totarget
- must delete a link from
opt.oldTree
must be an object, mapping file paths to lists of links. It should resemble the tree generated before.
opt.saveTree(tree, cb)
should persist the newly generate tree of links.
If you have a question, found a bug or want to propose a feature, have a look at the issues page.