Когда вы используете %sh
, вы выполняете команды оболочки на узле драйвера, используя его локальную файловую систему. Однако /FileStore/
не находится в локальной файловой системе, поэтому у вас возникла проблема. Вы можете увидеть это, попробовав:
%sh ls /FileStore
# ls: cannot access '/FileStore': No such file or directory
против
dbutils.fs.ls("/FileStore")
// resX: Seq[com.databricks.backend.daemon.dbutils.FileInfo] = WrappedArray(...)
Вы должны либо использовать утилиту распаковки, которая может работать с файловой системой Databricks, либо скопировать zip из хранилища файлов на диск с драйвером, разархивируйте, а затем скопируйте обратно в /FileStore
.
Вы можете обратиться к локальной файловой системе, используя file:/...
, например,
dbutils.fs.cp("/FileStore/file.zip", "file:/tmp/file.zip")
Надеюсь, что это помогает.
Примечание 1: Управление файловой системой Databricks не является сверхинтуитивным, особенно когда дело доходит до хранилища файлов. Например, теоретически файловая система Databricks (DBFS) монтируется локально как /dbfs/
. Однако /dbfs/FileStore
не обращается к хранилищу файлов, а dbfs:/FileStore
-. Ты не одинок. :)
Примечание 2: если вам нужно сделать это для многих файлов, вы можете распределить работу среди работников кластера, создав Dataset[String]
с путями к файлам и затем ds.map { name => ... }.collect()
. Действие по сбору приведет к выполнению. В теле функции map вы должны будете использовать API-интерфейсы оболочки вместо %sh
.
. Примечание 3: некоторое время назад я использовал следующую утилиту Scala, чтобы разархивировать Databricks. Не могу проверить, все еще работает, но это может дать вам некоторые идеи.
def unzipFile(zipPath: String, outPath: String): Unit = {
val fis = new FileInputStream(zipPath)
val zis = new ZipInputStream(fis)
val filePattern = """(.*/)?(.*)""".r
println("Unzipping...")
Stream.continually(zis.getNextEntry).takeWhile(_ != null).foreach { file =>
// @todo need a consistent path handling abstraction
// to address DBFS mounting idiosyncracies
val dirToCreate = outPath.replaceAll("/dbfs", "") + filePattern.findAllMatchIn(file.getName).next().group(1)
dbutils.fs.mkdirs(dirToCreate)
val filename = outPath + file.getName
if (!filename.endsWith("/")) {
println(s"FILE: ${file.getName} to $filename")
val fout = new FileOutputStream(filename)
val buffer = new Array[Byte](1024)
Stream.continually(zis.read(buffer)).takeWhile(_ != -1).foreach(fout.write(buffer, 0, _))
}
}
}