递归复制时对象和/或路径中的国际字符可能存在问题

Posted

技术标签:

【中文标题】递归复制时对象和/或路径中的国际字符可能存在问题【英文标题】:Possible issue with international characters in objects and/or paths when copying recursively 【发布时间】:2013-08-12 19:29:13 【问题描述】:

在使用 gsutil 上传大量图像后,我遇到了一个奇怪的问题 - 上传的文件无法通过 Google Cloud Console 看到,如果我尝试执行“gsutil ls”,gsutil 本身就会抱怨。我 99% 确定这与在目录名称中使用“å”或“Å”以及空格有关。

所有上传都是从根文件夹递归完成的(多级子目录中的大型图像集合)。如果我尝试再次上传文件,gsutil 会跳过它们,因为它们已经在那里,所以上传功能会做 something - 它的工作方式与列表和下载不同。

一个例子:

gsutil cp -R -n /Volumes/Photos/digitalfotografen.dk/2009/2009-05-30\ Søgården\ -\ bryllup/ gs://digitalfotografen/2009/
Skipping existing item: gs://digitalfotografen/2009/2009-05-30 Søgården - bryllup/Søgården 0128.CR2
...

好的 - 文件在那里,但通过 Google Cloud Console 浏览目录显示“无结果”。

还有:

gsutil ls gs://digitalfotografen/2009/2009-06-27 Søgården - reklamefotos/20090627_IMG_0128.CR2
CommandException: "ls" command does not support "file://" URIs. Did you mean to use a gs:// URI?

我尝试转义空格并以不同的方式使用引号,但没有成功。

现在,有趣的是:

gsutil cp -R -n /Volumes/Photos/digitalfotografen.dk/2009/2009-05-30\ Søgården\ -\ bryllup/ gs://digitalfotografen/2009/
Copying file:///Volumes/Photos/digitalfotografen.dk/2009/2009-05-30 Søgården - bryllup/Søgården 0128.CR2 [Content-Type=application/octet-stream]...

这里我在source端专门复制了带有转义空格的文件夹,现在文件再次上传。这将创建另一个同名文件夹(至少在 Cloud Console 中如此显示),并且文件现在在 both 文件夹中可见。

我们在丹麦字符集中使用了标准美国 ASCII 之外的三个不同字符(“æøå”和大写“ÆØÅ”),但问题似乎影响“å”和“ Å" - 其他两个单独或组合工作正常。我的预感是“å”和“Å”可能会在 ASCII 中翻译成完全不同的东西,当允许 gsutil 根据根文件夹的名称自行处理目录命名时(进行多级递归),这会使事情偏离轨道) 但在用户指定根文件夹的转义名称时有效。

这可能是 python 问题,而不是 gsutil 问题,但我没有资格确定这一点,因为除了一些大杂烩 shell 脚本之外,我对编程的了解几乎为零。

【问题讨论】:

这看起来确实是一个错误。我们正在调查。当我们有更新时,我会在这里发布。 非常感谢。一些附加信息:使用递归副本创建的文件夹无法通过 Cloud Console 再次删除,但可以通过 gsutil if 将文件夹作为通配符提供 before 'å'。示例:localhost:~ anders$ gsutil rm -R gs://digitalfotografen/2009/'2009-06-06 Søgå'* CommandException: No URIs matched: gs://digitalfotografen/2009/2009-06-06 Søgå* 删除通配符前的最后一个 'å':localhost:~ anders$ gsutil rm -R gs://digitalfotografen/2009/'2009-06-06 Søg'* Removing gs://digitalfotografen/2009/2009-06-06 Søgården - grillaften/... 如果您不介意确认它对您有用,现在应该修复它。 【参考方案1】:

我们在使用 gsutil 进入 ubuntu wsl 版本的 windows 10 时遇到了问题。 命令 gsutil 可以在 shell 中完美运行,但在包含到 shell 脚本中时不起作用:

gsutil -m ls -lr gs://project.appspot.com/

错误:

commandexception: "ls" command does not support "file://" urls. did you mean to use a gs:// url?

通过直接调用脚本 /usr/lib/google-cloud-sdk/platform/gsutil/gsutil 而不是调用链接 /usr/bin/gsutil 来解决云:

/usr/lib/google-cloud-sdk/platform/gsutil/gsutil -m ls -lr gs://project.appspot.com/

我不知道为什么,但它正在工作。

感谢 Marion 为我们提供了如此罕见的错误 :-)

【讨论】:

【参考方案2】:

我知道这是一个老错误,但我遇到了与上述类似的问题。

CommandException: "ls" command does not support "file://" URLs. Did you mean to use a gs:// URL?

使用 Scala 代码中的gsutil

import sys.process._


object Main 
  def main(args: Array[String]): Unit = 
    val clients = s"gsutil ls gs://<bucket name>".!!
    val beforeDate: String = "date +%Y-%m-%d -d '-8 days'".!!
    val clientList = clients.split("\n").map(f => f.split('/').apply(1)).toList
    for (x <- clientList) 
      val countImg = (s"gsutil -m ls gs://<bucket name>/$x/$beforeDate.stripLineEnd" #| "wc -l").!!
      println(countImg)
    
  

所以我发现beforeDate 上有一个LineEnd 字符,当我条纹化时错误消失了。因此,当gs://... 路径中有“特殊”字符时会发生错误。所以一定要去掉任何“特殊”字符的变量。 而这一切的发生只是因为我懒得使用java.time.LocalDate 来生成beforeDate 变量。希望这里能帮助遇到同样错误的其他人。

【讨论】:

以上是关于递归复制时对象和/或路径中的国际字符可能存在问题的主要内容,如果未能解决你的问题,请参考以下文章

是否有可能检查我进入的对象是否存在但指向 Null? [关闭]

如何检查 Javascript 中是不是存在字符串/数组/对象? [复制]

owl中的递归对象属性

递归列出给定路径下的所有文件和文件夹? [复制]

File类&递归&IO流

GMT 和 UTC 一样吗? [复制]