基本想法是:我有一个bash脚本,在其中自动将文件从一个目录移动到另一个目录。
问题是:当我运行脚本时,有时会从mv命令得到以下错误:“mv: cannot stat '/shares/directory with spaces/test file.txt': No such file or directory”。vm命令的错误代码是1。更奇怪的是,有时文件移动实际上会成功。
此外,我在脚本中有一个逻辑分支,交替使用rsync移动/复制特定文件(与上述mv命令相同的本地文件系统源和目标)。我遇到了一个类似于stat()系统调用的错误:
“rsync: link_stat "/shares/directory with spaces/test file.txt" failed: No such file or directory (2) rsync error: some files/attrs were not transferred (see previous errors) (code 23) at main.c(1070) [sender=3.0.9]”
当运行脚本时,这个错误不总是出现。有时它会完成文件移动而没有任何抱怨,而其他时候连续运行脚本时会始终返回错误。
还有一个额外的因素需要注意(我越来越怀疑这是我的困扰的关键因素):/shares/目录是Dropbox安装监视的目录,意味着它被监视并由Dropbox安装镜像。此时,我无法确定dropboxd是否以某种方式锁定了该文件,或者类似于此类的情况,使其无法进行stat操作。明确地说,这些文件最终会在没有进一步干预的情况下从此状态中释放,并且可以使用mv移动。
代码如下:
“mv -v --no-clobber "${SOURCEPATH}${item}" "${DESTINATIONPATH}${item}"”
更多信息:
以下内容可能与问题有关:
- mount指示文件系统为ext4 - 假定,由于脚本是由root运行的,所以所有权和权限不应该是问题。尤其是如果文件系统不是基于fuse的。 - 路径中的基本“目录”(例如/shares/)是指向同一文件系统上另一个目录的符号链接。 - Linux的版本是Debian。
故障排除:
为了消除变量扩展或其内容的任何问题,我尝试像这样硬编码bash脚本:
mv -v --no-clobber "/shares/directory with spaces/test file.txt" "/new destination/directory with spaces/test file.txt"
通过 ls -al
验证 "test file.txt" 存在。参考权限为:-rw-r--r--
不幸的是,这也导致相同的错误。
我能想到的其他可能问题以及我为了尝试排除它们所做的事情:
>> 可能问题: 慢的HDD(或驱动器处于低功耗模式)或外部USB驱动器
>> 结果: 所有驱动器都是本地SATA磁盘,设置为不停放磁头。此外,即使强制从文件系统进行一致读取,仍然会发生相同的错误。
>> 可能问题: 非Linux、NFS或fuse基础的文件系统
>> 结果: 没有,源和目标都在同一个本地文件系统上,并且 mount
表示文件系统是ext4
>> 可能问题: 文件路径中的空格或其他不可打印字符
>> 结果: 验证源路径和目标路径都正确地包含在引号中
>> 可能问题: 转义换行符后的续行问题(换行符后的空格)
>> 结果: 确保命令都在一行上,仍然是相同的错误
>> 可能问题: globbing(在指定要移动的文件时使用*)
>> 结果: 没有,在路径和名称中直接指定每个文件
>> 可能问题: 由于使用本地路径而导致的路径混淆
>> 结果: 没有,文件路径从 / 开始完全合格
>> 可能问题: 实际上没有在指定的路径中找到文件
>> 结果: 没有,在执行脚本之前通过 ls -al
验证了文件存在
>> 可能问题: --no-clobber 的 mv 导致问题
>> 结果: 没有,尝试了没有它,相同的错误
>> 可能问题: 只有通过Dropbox同步到文件系统的文件存在问题
>> 结果: 没有,直接通过 touch new-local-file.txt
创建本地文件也会产生相同的 stat() 错误
mv
和rsync
产生类似的stat()错误,这让我相信:
- 在bash脚本中存在某些系统性的潜在边界情况(例如文件权限/所有权或文件忙)没有被考虑;或者
- 同样的bug困扰了我在
mv
和rsync
场景中。
mv
的退出代码> 0时在文件上运行/usr/bin/stat
。我打开了2个shell:在其中一个shell中,我运行了while true; do find . -exec stat {} \;; done
。我将文件复制到源路径中,并在循环的stat
中看到它正常显示。在另一个shell中,我运行了bash脚本。mv
和stat
抛出错误“无法stat ...没有这样的文件”。尽管来自'mv'的错误,但实际上已移动文件。这解释了为什么stat
会引发错误,但并不解释为什么mv
会这样做。成功的文件移动也通过循环的stat
输出得到了验证。 - John Mark Mitchell