![在可能发生名称冲突的情况下将文件和子目录“向上子目录”移动的便捷方法是什么?](https://linux22.com/image/130852/%E5%9C%A8%E5%8F%AF%E8%83%BD%E5%8F%91%E7%94%9F%E5%90%8D%E7%A7%B0%E5%86%B2%E7%AA%81%E7%9A%84%E6%83%85%E5%86%B5%E4%B8%8B%E5%B0%86%E6%96%87%E4%BB%B6%E5%92%8C%E5%AD%90%E7%9B%AE%E5%BD%95%E2%80%9C%E5%90%91%E4%B8%8A%E5%AD%90%E7%9B%AE%E5%BD%95%E2%80%9D%E7%A7%BB%E5%8A%A8%E7%9A%84%E4%BE%BF%E6%8D%B7%E6%96%B9%E6%B3%95%E6%98%AF%E4%BB%80%E4%B9%88%EF%BC%9F.png)
我的目录中有一些文件和目录/var/foo/bar/baz
。现在,我想将它们全部移至/var/foo/bar
,并摆脱 baz。容易,对吧?
cd /var/foo/bar
mv baz/* .
rmdir baz
(为了讨论的目的,我忽略了以 . 开头的文件)
但!如果baz/
包含名为 的非目录文件怎么办baz
?我可以将其移动到其他地方,或者使用临时文件名,然后删除该目录baz
,然后将其移动到位。但这很乏味,而且命令也很多……还有另一种习惯的、更简单/更优雅的方法吗?
笔记:
- 如果存在其他名称冲突,
mv
则覆盖(并且可能提示)的正常语义是可以的。但对于baz
,它不会这样做,它只会失败。
答案1
cd /var/foo/bar/baz
for src in *; do
dest="${src}"
suffix=0
while [[ -e ../"${dest}" ]]; do
dest="${src}.${suffix}"
suffix=$((suffix+1))
done
mv -n "$src" ../"$dest"
done
cd ..
rmdir baz
一个相当简单的解决方案。准备将文件从当前目录移动到父目录,但如果已存在具有该名称的文件,请添加带有数字的后缀。但请确保不要使用以下数字还由于某种原因已经存在了。
如果任何被调用的东西存在,无论是目录、套接字、常规文件还是任何其他可能存在的东西, 该构造[[ -e file ]]
将返回 true。file
答案2
这太长了,但应该可以:
cd /var/foo/bar
bazbaz_tmp_file=$(mktemp baz/XXXXXXXXXXXXXX)
[[ -e baz/baz ]] && mv baz/baz $bazbaz_tmp_file
mv baz/* .
rmdir baz
mv $(basename $bazbaz_tmp_file) baz
注意:这假设我们可以安全地将任何其他文件从baz/
.