我在 bash 脚本中移动文件时遇到问题。对于同一个问题,我一直在尝试在这里找到的不同解决方案,但找不到任何有效的解决方案。
我的最后一次尝试是添加shopt -s dotglob nullglob
,但这并没有解决任何问题..
在这次测试中,
jdir0="/media/sf_Mediaserver3/test22/abbamax.(6th.copy)..kansas.(1999)"
mv -v "$jdir0/*" "$jdir0/subs/" &>> $debuglog
..我得到:
mv: cannot stat '/media/sf_Mediaserver3/test22/abbamax.(6th.copy)..kansas.(1999)/*': No such file or directory
但是,是的,有!
drwxrwx--- 1 root vboxsf 4096 Aug 22 07:06 ../
-rwxrwx--- 1 root vboxsf 0 Aug 21 17:19 'kallee.(222)..nnn.srt'*
-rwxrwx--- 1 root vboxsf 159363 Aug 21 17:26 'movie.test(2929).ismim.mp4'*
drwxrwx--- 1 root vboxsf 0 Aug 22 07:06 subs/
(这些名称确实很奇怪的原因是我在这个函数之前正在测试删除无效字符)
更新:显然我遇到了间歇性错误,几天后我终于将其追溯到服务器问题(文件存储的位置)。显然,如果服务器未完成保存/名称更改,并且脚本要求它执行新操作,则会发生这些错误。例如,将文件 A 重命名为 B,然后在服务器执行第一个请求之前要求其将 B 重命名为 C,这导致服务器说:B 不存在,这当然会导致错误代码。
答案1
*
是 shell 的全局运算符。它需要不被引用才能被识别。当引用时,/media/sf_Mediaserver3/test22/abbamax.(6th.copy)..kansas.(1999)/*
按字面意思传递到mv
并mv
尝试移动名为 的文件*
,但没有这样的文件。
所以你需要:
mv -v -- "$jdir0"/* "$jdir0/subs/" >> "$debuglog" 2>&1
让 shell"$jdir0"/*
在调用之前展开到匹配文件列表中mv
。
你做不是想要nullglob
在这里,因为这意味着在没有与该"$jdir0"/*
模式匹配的文件的情况下,mv
将仅使用 调用-v
,--
并media/sf_Mediaserver3/test22/abbamax.(6th.copy)..kansas.(1999)/subs/
导致 令人困惑的语法错误mv
。
failglob
在这种情况下,当全局不匹配时中止命令可能是更好的选择,但请注意,bash
在这种情况下,根据调用命令的上下文,以不一致的方式中止,这使得该选项在脚本中使用起来很棘手。
dotglob
是允许 glob 匹配隐藏文件。
现在,请注意,glob 会匹配文件,无论其类型如何,因此*
上面的内容也将匹配subs
.如果subs
是目录的符号链接,mv
则将很乐意将该subs
符号链接移动到该目录中,从而导致所有后续移动失败,因为subs
目标目录现已消失。如果subs
是一个普通的子目录,mv
可能会抱怨它无法将目录移动到其自身中。
所以你可能想这样写:
shopt -s extglob
mv -v -- "$jdir0"/!(subs) "$jdir0/subs/" >> "$debuglog" 2>&1
!(pattern)
与任何文件名匹配的 ksh 扩展 glob 运算符在哪里不是匹配pattern
,因此这里移动除subs
.
另请注意,在bash
shell 中,即使在非交互式 shell 实例中,在重定向目标中也需要引用参数扩展(bash 处于 POSIX 模式时除外)。
¹ 除非您使用 zsh 而不是 bash 及其 glob 限定符,例如*(.)
仅移动常规的文件