我正在尝试使用以下命令将数千个文件上传到Google云端存储:
gsutil -m cp *.json gs://mybucket/mydir
但是我收到了这个错误:
-bash: Argument list too long
处理此问题的最佳方法是什么?我显然可以编写一个bash脚本来迭代不同的数字:
gsutil -m cp 92*.json gs://mybucket/mydir
gsutil -m cp 93*.json gs://mybucket/mydir
gsutil -m cp ...*.json gs://mybucket/mydir
但问题是我事先并不知道我的文件名是什么,所以写这个命令并不是一件容易的事。
是否有办法用gsutil
本地处理此问题(我不这么认为,from the documentation),或者在bash中处理此问题的方法,我可以列出10,000个文件一次,然后将它们传递给gsutil
命令?
答案 0 :(得分:14)
Eric的答案应该有效,但另一个选择是依靠gsutil的内置通配符,引用通配符表达式:
gsutil -m cp "*.json" gs://mybucket/mydir
要解释更多:"参数列表太长"错误来自shell,它具有扩展通配符的有限大小缓冲区。通过引用通配符可以防止shell扩展通配符,而shell会将该文本字符串传递给gsutil。然后,gsutil以流式方式扩展通配符,即在执行操作时扩展它,因此它永远不需要缓冲无限量的扩展文本。因此,您可以使用gsutil通配符而不是任意大的表达式。在对象名称上使用gsutil通配符时也是如此,例如,这将起作用:
gsutil -m cp "gs://my-bucket1/*" gs://my-bucket2
即使gs:// my-bucket1。
的顶层有十亿个对象答案 1 :(得分:2)
如果您的文件名不受新行的限制,您可以使用gsutil cp
从stdin
读取
find . -maxdepth 1 -type f -name '*.json' | gsutil -m cp -I gs://mybucket/mydir
或者,如果您不确定自己的姓名是否安全且find
和xargs
支持,则可以
find . -maxdepth 1 -type f -name '*.json' -print0 | xargs -0 -I {} gsutil -m cp {} gs://mybucket/mydir
答案 2 :(得分:1)
以下是您可以使用xargs
限制一次传递给gsutil
的文件数量的方法。空字节用于防止文件名中的空格或换行符出现问题。
printf '%s\0' *.json | xargs -0 sh -c 'copy_all () {
gsutil -m cp "$@" gs://mybucket/mydir
}
copy_all "$@"'
这里我们定义一个函数,用于将文件参数放在gsutil
命令中的正确位置。整个过程应该以处理所有参数所需的最少次数发生,每次都可以传递最大数量的文件名参数。
或者你可以单独定义函数,然后export
它(这是特定于bash的):
copy_all () {
gsutil -m cp "$@" gs://mybucket/mydir
}
printf '%s\0' *.json | xargs -0 bash -c 'export -f copy_all; copy_all "$@"'