是否有一种优雅的方法可以将当前目录中的所有子目录移动到新的子目录?

是否有一种优雅的方法可以将当前目录中的所有子目录移动到新的子目录?

我经常遇到以下情况。我在一个有多个子目录的目录中,如下所示

$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如果也想移动文件,请删除。

相关内容