查找和转换HTML文件并移动它们En-Masse

时间:2011-11-15 15:12:53

标签: wolfram-mathematica

我正在使用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 SetDirectoryCreateDirectory,否则它会一直遇到麻烦。

这一切似乎有点令人困惑。基本上,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[]动态执行此操作时遇到问题。)

我为这里的混乱道歉 - 我知道它显示了这个问题..

2 个答案:

答案 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}}构造分配给函数,然后使用它来递归树。

这很简单,但我不确定这是你想要的。也许你可以对你所追求的内容更加明确,所以我/我们不会坐下来编写错误的东西。