我经常遇到以下情况。我在一个有多个子目录的目录中,如下所示
$ls
a b c d
我想a-d
通过将目录移动到名为 的同级新目录中来存档目录archive
。即:
$ls
archive
$ls archive
a b c d
我目前的做法是先制作archive
,然后移动所有。但我不喜欢这样,因为您总是会收到错误“mv:无法将“archive”移动到其自身的子目录“archive/archive”。虽然这有效,但我不喜欢我“滥用”内置异常处理的事实。
$mkdir archive
$mv * archive/
`mv: cannot move 'archive' to a subdirectory of itself, 'archive/archive'
理想情况下,我希望找到一个不涉及错误的解决方案。类似于 mv 自动创建目录的方法,但不幸的是,这不起作用。
$mv * archive/
mv: target 'archive/' is not a directory
答案1
Bash 特定的方法是使用GLOBIGNORE
:
GLOBIGNORE=archive
(或者GLOBIGNORE=archive:.*
,看看文档)。
*
然后in (或任何位置)的扩展mv * archive/
将不包含archive
.unset GLOBIGNORE
之后或提前计划并在子 shell 中运行命令:
(GLOBIGNORE=archive; mv * archive/)
注意,这GLOBIGNORE=archive mv * archive/
将不起作用,因为您需要在扩展的 shell 中*
而不是在 的环境中使用该变量mv
。
答案2
*
在创建之前存储扩展的结果archive
。例如:
set -- *
mkdir archive
mv -- "$@" archive/
(--
解释)
上述解决方案是可移植的。
在单独的 (子) shell 中运行代码以保留原始位置参数。或者在 Bash 中(但不在 plain 中sh
)使用数组:
foo=(*)
mkdir archive
mv -- "${foo[@]}" archive/
unset foo
但你需要选择一个没用过name(此处foo
:),否则您将丢失变量的原始内容。因此使用子 shell 仍然是一个好主意。如果在子 shell 中,那么不使用可移植方法是没有意义的。生成的代码可能是:
(
set -- *
mkdir archive
mv -- "$@" archive/
)
注意mkdir
可能会失败。通常,当您以交互方式工作(键入命令)时,这不是问题。但是,( )
只有在您发送结束代码后,代码片段才会运行)
。出于这个原因,如果失败,您可能希望中止mkdir
(例如mkdir archive || exit 1
)。或者在交互式子 shell 中工作:
# interactively
bash # starting a child shell
# now interactively in a new shell
set -- *
# do whatever you need to do
exit # exiting the child shell
# now back in the original shell
实际上,我可能会忘记exit
。这个错误以后可能会造成混淆,也可能不会。
坦白说,你多久需要一次原始位置参数交互的shell?你可能不需要它们,所以第一个没有子 shell 的代码片段(简单直接) 应该没事。
答案3
对子目录进行一级深度扫描的 find 命令也会执行到存档目录的移动:
# Create archive dir if not present
mkdir -p archive
# Test first with echo command:
find . -maxdepth 1 -mindepth 1 -type d ! -name archive -exec echo mv {} archive \;
# Run it:
find . -maxdepth 1 -mindepth 1 -type d ! -name archive -exec mv {} archive \;
-type d
如果也想移动文件,请删除。