我正在使用Mathematica处理大量网站文件,我已将其镜像到我自己的系统上。它们分布在数百个目录中,有大量的子目录。例如,我有:
/users/me/test/directory1
/users/me/test/directory1/subdirectory2 [times a hundred]
/users/me/test/directory2
/users/me/test/directory2/subdirectory5 [etc. etc.]
我需要做的是进入每个目录,Import[]
将所有HTML文件作为纯文本,然后将它们放在我的系统上以'directory1'命名的其他目录中。到目前为止,使用Do[]
循环我已经能够做一个粗略的版本:但是,我现在最好的情况是将“.txt”文件转储到原始目录中,这不是一个理想的解决方案因为它们仍然遍布我的系统。
要查找我的文件,请使用directoryfiles = FileNames["*.htm*", {"*"}, Infinity];
一些额外的烦恼问题:
(1)重复:Mathematica是否有办法处理重复项 - 即如果我们遇到另一个index_en.html,它是否可以重命名为index_en_1.html?
(2)目录:由于所有目录,除非我一遍又一遍地使用Mathematica SetDirectory
和CreateDirectory
,否则它会一直遇到麻烦。
这一切似乎有点令人困惑。基本上,Mathematica是否有一种有效的方法可以找到分布在数百个目录/子目录中的大量HTML文件,将它们作为纯文本导入,然后将它们导出到其他地方[对我来说知道它们来自directory1非常重要,但就是这样] 。
- 为了清晰起见而编辑 -
以下是我目前的代码:
SetDirectory[
"/users/me/web/"];
dirlist = FileNames[];
directoryPrefix =
"/users/me/web/";
plainHTMLBucket = "";
Do[
directory = directoryPrefix <> dirname;
exportPrefix =
"/users/me/desktop/bucket/";
SetDirectory[directory];
allFiles = FileNames["*.htm*", {"*"}, Infinity];
plainHTMLBucket = "";
Do[
plainHTML = Import[filename, "Plaintext"];
plainHTMLBucket = AppendTo[plainHTMLBucket, plainHTML];
, {filename, allFiles}];
Export[exportPrefix <> dirname <> ".txt", plainHTMLBucket];
Print["We Have Reached Here"];
, {dirname, dirlist}];
从我的角度来看,这有什么问题?除了凌乱,这是我的解决方法:我宁愿将所有文件分开而不是一个大文件 - 即将每个导入和导出作为单独的文件,但在名为'directory1'的目录中,尽管在其他地方。问题在于镜像这些目录(目录不存在,但我在使用CreateDirectory[]
动态执行此操作时遇到问题。)
我为这里的混乱道歉 - 我知道它显示了这个问题..
答案 0 :(得分:8)
以下代码可能会起到作用:
mapFileNames[source_, filenames_, target_] :=
Module[{depth = FileNameDepth[source]}
, FileNameJoin[{target, FileNameDrop[#, depth]}]& /@ filenames
]
htmlTreeToPlainText[source_, target_] :=
Module[{htmlFiles, textFiles, targetDirs}
, htmlFiles = FileNames["*.html", source, Infinity]
; textFiles = StringReplace[
mapFileNames[source, htmlFiles, target]
, f__~~".html"~~EndOfString :> f~~".txt"
]
; targetDirs = DeleteDuplicates[FileNameDrop[#, -1]& /@ textFiles]
; If[FileExistsQ[target], DeleteDirectory[target, DeleteContents -> True]]
; Scan[CreateDirectory[#, CreateIntermediateDirectories -> True]&, targetDirs]
; Scan[
Export[#[[2]], Import[#[[1]], "Plaintext"], "Text"] &
, Transpose[{htmlFiles, textFiles}]
]
]
使用示例(警告:首先删除目标目录!):
htmlTreeToPlainText["/users/me/web", "/users/me/desktop/bucket"]
如何运作
各种Mathematica FileName...
函数在这种情况下很有用。首先,我们首先定义辅助函数mapFileNames
,该函数包含源目录,位于源目录中的文件名列表以及目标目录。它返回一个文件路径列表,用于命名目标目录下的相应位置。
mapFileNames[source_, filenames_, target_] :=
Module[{depth = FileNameDepth[source]}
, FileNameJoin[{target, FileNameDrop[#, depth]}]& /@ filenames
]
该函数使用FileNameDrop
从每个文件名中删除前导源路径元素,并FileNameJoin
将目标路径添加到每个结果的前面。要删除的前导元素的数量是通过将FileNameDepth
应用于源路径来确定的。
例如:
In[83]:= mapFileNames["/a/b", {"/a/b/x.txt", "/a/b/c/y.txt"}, "/d"]
Out[83]= {"/d/x.txt", "/d/c/y.txt"}
使用此功能,我们可以将源目录(source
)下的HTML文件路径列表转换为目标目录(target
)下的相应文本文件路径列表:
htmlFiles = FileNames["*.html", source, Infinity]
textFiles = StringReplace[
mapFileNames[source, htmlFiles, target]
, f__~~".html"~~EndOfString :> f~~".txt"
]
这些语句检索HTML文件列表,将它们映射到目标目录,然后将文件扩展名从.html
更改为.txt
。我们现在可以从生成的文本文件中提取必要的目录名称:
targetDirs = DeleteDuplicates[FileNameDrop[#, -1]& /@ textFiles]
再次使用FileNameDrop
,这次是从每个文本文件的路径中删除文件名部分。
接下来,我们需要删除目标目录(如果它已经存在)并创建新的必需目录:
If[FileExistsQ[target], DeleteDirectory[target, DeleteContents -> True]]
Scan[CreateDirectory[#, CreateIntermediateDirectories -> True]&, targetDirs]
我们现在可以执行HTML到文本的转换,在目标目录已经存在的情况下是安全的:
Scan[
Export[#[[2]], Import[#[[1]], "Plaintext"], "Text"] &
, Transpose[{htmlFiles, textFiles}]
]
答案 1 :(得分:4)
要设置当前目录,请执行类似
的操作SetDirectory["~/Desktop/"]
现在,假设我希望获取当前目录中所有目录的列表。我能做到
dirs=Pick[
#,
(FileType[#] == Directory) & /@ #
] &@FileNames[]
返回您之前设置的当前目录下所有目录的名称列表(我使用嵌套的纯函数,可能会令人困惑......)。然后,您可以通过fn
对每个dirs
Scan[fn,dirs]
Pick[]
{{1}}。因此,您可以将{{1}}构造分配给函数,然后使用它来递归树。
这很简单,但我不确定这是你想要的。也许你可以对你所追求的内容更加明确,所以我/我们不会坐下来编写错误的东西。