先来说说为什么会涉及到这块,再分享一下这个心路历程啊,最后才是解决方法(赶时间就直奔第三部分吧)
一、为什么会涉及到这块?
在运行BSgenomeForge包中forgeBSgenomeDataPkgFromNCBI函数的时候,一直报错啊,如下:
cannot rename file '/tmp/Rtmprdm2xy/single_sequences.2bit' to './BSgenome.Vcholerae.NCBI.ASM836960v1/inst/extdata/single_sequences.2bit', reason 'Invalid cross-device link'
大概意思就是目录A有个文件a,现在要把它移到目录B,但是呢就是'Invalid cross-device link'。
可是在命令行试了试,这两个目录都有读写权限,这是为什么呢?
ok,下面就是心路历程了
二、debug心路历程
小心思又来了,机脑现在不用何时用?把上面这段报错输进去,问它是什么原因以及如何解决,AI是这么回答的:
在 R 语言中,
file.rename()函数可能会因为尝试在不同的文件系统或者分区上移动文件而报错 "Invalid cross-device link"。这是因为rename系统调用不允许跨文件系统移动文件。以下是一些可能的解决方案:
-
使用
file.copy()和file.remove()组合:可以先复制文件到目标位置,然后删除原始文件。这种方法可以避免跨文件系统移动文件的问题。例如:
> if (file.exists(target_file)) {
+ file.remove(target_file)
+ }
+ file.copy(source_file, target_file)
+ file.remove(source_file)
这种方法在某些情况下被用作 file.rename() 的替代方案 。
检查文件系统:确保源文件和目标路径位于同一个文件系统上。如果它们位于不同的分区,你可能需要调整你的文件系统设置或选择不同的路径。
-
使用系统命令:在 R 脚本中使用系统命令
mv来移动文件。例如:system(paste("mv", shQuote(source_file), shQuote(target_file)))这种方法可以利用系统级的文件移动命令,它通常会处理跨文件系统的情况。
避免在脚本中硬编码路径:如果可能,避免在脚本中硬编码文件路径,而是使用相对路径或让用户提供路径,这样可以减少跨文件系统操作的可能性。
检查 R 版本和操作系统:有时候,特定版本的 R 或操作系统可能会有已知的 bug 或限制。确保你的 R 是最新版本,并且查看相关的 R 社区或论坛是否有相关的讨论或修复。
使用其他 R 包:有些 R 包可能提供了更健壮的文件操作功能,可以处理跨文件系统的问题。例如,
fs包提供了跨平台的文件系统操作功能。
AI就是系统啊,一个一个来吧,简单看了一下前三个,1和3差不多,都需要去找到函数的源代码,去把rename改成copy或者mv,好,应该不太难,一行一行运行就行了呗,走起:
> pkg_maintainer="pglaser@pasteur.fr"
> pkg_author = NA
> check_pkg_maintainer(pkg_maintainer)
Error in check_pkg_maintainer(pkg_maintainer) :
could not find function "check_pkg_maintainer"
第一步就给我整懵了,这个check_pkg_maintainer函数不存在,它是个啥玩意儿呢,去安装包源代码里边找吧,好了,作者给封上了,啥也看不见,这咋整?
又回头看了看AI给的第2个方案,注意到“分区”两个字,难道不能rename是因为目录A和B在不同的分区?看了一下,果真是,那,解决分区问题就是了。
三、解决方法
- 要么在A下面运行这个函数,很好办,但需要注意A盘的内存啊,我们的/tmp内存很小,所以放弃这个方法
- 要么就把临时文件改到和B同区的路径,这碗饭合胃口,那就改临时文件路径吧,走起(在R环境运行啊朋友们)
#change the tempdir() location
> tempdir <- function() "/home/x/tmp/data" # 这里引号里就写自己想要放临时文件的目录就好了
> unlockBinding("tempdir", baseenv())
> utils::assignInNamespace("tempdir", tempdir, ns="base", envir=baseenv())
> assign("tempdir", tempdir, baseenv())
> lockBinding("tempdir", baseenv())
一行一行跟着来就对了,最后再检查一下:
> tempdir ()
[1] "/home/x/tmp/data"
> tempfile()
[1] "/home/x/tmp/data/file4a111ff7ff02"