高级文件管理
让我们想象一个情况,我们有几个数据集分布在文件夹中,文件夹中也可能有垃圾(带有有趣浣熊的图片,文本文档)。 我希望能够找到必要的文件,以便以后与他们一起工作。 Julia只实现文件的基本工作-<https://engee.com/helpcenter/stable/ru-en/julia/base/file.html >。
在这篇文章中,我将制作一个更聪明的工具来处理文件。
我们将如何工作?
我们不会进入文件系统如何工作的细节-我们不需要它。 只要观察到目录和文件的结构惊人地类似于一棵树就足够了。 树是一种特殊的图形。 在这样的图中,除了"根"之外的所有节点都有一个父节点。:
用于图遍历和图修改的最优算法对于这样的图是已知的,并且它们通常已经实现。 我的想法如下:我将文件夹的内容表示为一棵树,树的每个节点都是一个文件或文件夹。 我将分别保留路径,名称,扩展名,创建和修改的日期和时间,以及文件夹属性。 并且为了组织一个树结构,我将存储这个节点的"后代"。:
In [ ]:
using Dates
struct FileTreeNode
path::String
name::String
ext::String
isdir::Bool
created::DateTime
modified::DateTime
children::Vector{FileTreeNode}
end
此外,我们还将创建辅助函数来获取文件创建和修改的日期和时间,以及获取文件名、路径和扩展名。:
In [ ]:
function get_metadata(path::String)
st = stat(path)
created = unix2datetime(st.ctime)
modified = unix2datetime(st.mtime)
return created, modified
end
function split_name_ext(path::String)
name = basename(path)
base, ext = splitext(name)
return base, ext
end
Out[0]:
种植一棵树
我们有一切需要实现,我们可以创建一个基于目录结构的树。
使用 readdir 我们将获取当前文件夹内的文件和文件夹列表,然后对检测到的文件夹重复此操作。 这称为递归。
以编程方式,我们执行文件和文件夹树的递归遍历。**
让我们为我们的功能添加一个限制:搜索深度。
In [ ]:
function build_tree(path::String; maxdepth=typemax(Int), depth=0)
is_dir = isdir(path)
name, ext = split_name_ext(path)
created, modified = get_metadata(path)
if is_dir && depth < maxdepth
entries = readdir(path; join=true)
children = [
build_tree(e; maxdepth, depth=depth+1)
for e in sort(entries)
]
else
children = FileTreeNode[]
end
return FileTreeNode(path, name, ext, is_dir, created, modified, children)
end
Out[0]:
In [ ]:
import AbstractTrees: children, printnode
children(node::FileTreeNode) = node.children
function printnode(io::IO, node::FileTreeNode)
if node.isdir
print(io, "📁 ", node.name)
else
print(io, "📄 ", node.name, node.ext)
end
end
Out[0]:
In [ ]:
tree = build_tree(".",maxdepth=2)
using AbstractTrees: print_tree
print_tree(tree)