如果我使用命令
wget --no-remove-listing -P ...../debugdir/gnu/<dir>/ ftp:<ftp-site>/gnu/<dir>/
我将获取.listing
该目录的文件。但我必须遍历每个后续子目录才能获取整个结构。有没有办法用.listing
一个命令从所有(子)目录中获取文件?
另外,我注意到index.html
每次访问后都会自动生成该文件。有没有办法抑制这种行为?
问题在于我总是发现 Bash 处理很慢,但经过一些分析后我发现最大的延迟是.listing
从后续子目录获取每个文件。
示例:检查 GNU 树中的特定文件扩展名大约需要 320 秒,其中 290 秒用于处理上述wget
命令。
答案1
如果您希望建立 FTP 站点的索引,即列出站点上的所有子目录和文件而不实际检索它们,您可以执行以下操作:
wget -r -x --no-remove-listing --spider ftp://ftp.example.com/
在哪里,
- -r => 递归(即访问子目录)
- -x => 强制在客户端上创建镜像子目录
- --no-remove-listing => 在每个子目录中保留“.listing”文件
- --spider => 访问但不检索文件
这将在客户端和服务器上创建一个结构相同的稀疏目录树,其中仅包含显示每个目录内容的“.listing”文件(“ls -l”的结果)。如果您想将其分解为一个路径限定文件名列表(就像您从“find . -type f”中获得的一样),请在该稀疏目录树的根目录中执行以下操作:
find . -type f -exec dos2unix {} \;
( find . -maxdepth 999 -name .listing -exec \
awk '$1 !~ /^d/ {C="date +\"%Y-%m-%d %H:%M:%S\" -d \"" $6 " " $7 " " $8 "\""; \
C | getline D; printf "%s\t%12d\t%s%s\n", D, $5, gensub(/[^/]*$/,"","g",FILENAME), $9}' \
{} \; 2>/dev/null ) | sort -k4
这将给你类似的输出
2000-09-27 00:00:00 261149 ./README
2000-08-31 00:00:00 727040 ./foo.txt
2000-10-02 00:00:00 1031115 ./subdir/bar.txt
2000-11-02 00:00:00 1440830 ./anotherdir/blat.txt
注意:在此用例中,“-maxdepth 999”选项不是必需的,我将其留在了我正在测试的调用中,该调用有一个额外的约束:限制报告的树的深度。例如,如果您扫描包含多个项目的完整源树的站点,例如
./foo/Makefile
./foo/src/...
./foo/test/...
./bar/Makefile
./bar/src/...
./bar/test/...
那么您可能只需要项目和顶级目录的概要。在这种情况下,您可以给出类似“-maxdepth 2”的选项。
答案2
此解决方案的一个严重问题是“--spider”会导致 wget 传输每个文件但不将任何数据写入磁盘。这意味着您将有效地下载 FTP 服务器的全部内容。这可能会产生不良后果,例如(但不仅限于此):产生 ISP 入口流量超额费用,当您的 WAN 链路充斥着不必要的 FTP 数据传输时,会中断其他 IP 服务(如 VoIP/IPTV/VoD),并且可能会提示 FTP(无镜像/请求镜像策略)服务器的管理员拒绝从您的公共 IP 进行访问,因为对他们来说,这看起来就像有人递归下载整个站点一样。也就是说,由于我们只想获取目录索引,因此用简单的 REGEX 接受选项“-A '.listing'”替换“--spider”是更好的选择,因为它会导致 wget 拒绝从服务器下载除“.listing”文件之外的任何数据。
PS@Codex24 - 您的一行代码用于解析/报告 - 做得好!