移动不是目录的每个文件

Que*_*ark 20 bash directory wildcards mv

我有一个要清理的目录,其中包含文件和子目录。我想要做的很简单:将所有文件移动到另一个目录中,但保留所有子目录。

我在想这样的事情:

mv [*_but_no_dirs] ./other_directory
Run Code Online (Sandbox Code Playgroud)

似乎应该有一种简单的方法来使用通配符*和正则表达式来做到这一点......

有人有想法吗?

Gil*_*il' 17

此处不涉及正则表达式。bash 中的通配符(与大多数其他 shell 一样)仅根据文件名匹配文件,而不是根据文件类型或其他特征。有一种按类型匹配的方法:/在模式末尾添加使其仅匹配目录或目录的符号链接。通过这种方式,您可以移动目录,然后移动剩下的内容,然后将目录移回——虽然麻烦,但确实有效。

tmp=$(TMPDIR=.. mktemp -d)
mv -- */ "$tmp"
mv -- * other_directory/
mv "$tmp"/* .
rmdir "$tmp"
Run Code Online (Sandbox Code Playgroud)

(如果当前目录是文件系统的挂载点,则应避免这种方法,因为这意味着将目录移走和移回必须将其中的所有数据复制两次)。

按类型匹配文件的标准方法是调用find.

find . -name . -o -type d -prune -o -exec sh -c 'mv "$@" "$0"' other_directory/ {} +
Run Code Online (Sandbox Code Playgroud)

(也移动符号链接,无论它们是否指向目录)。

在 zsh 中,您可以使用glob 限定符按类型匹配文件。在.预选赛符合规则的文件; 用于^/匹配所有非目录,或-^/排除指向目录的符号链接。

mv -- *(.) other_directory/
Run Code Online (Sandbox Code Playgroud)

在任何 shell 中,您都可以简单地循环。

for x in *; do
   if ! [ -d "$x" ]; then
     mv -- "$x" other_directory/
   fi
done
Run Code Online (Sandbox Code Playgroud)

(不会将符号链接移动到目录)。


Val*_*ami 13

你可以使用类似的东西

find . -maxdepth 1 \( ! -type d \) -exec sh -c 'mv  "$@" MYDIR' _ {} \;
Run Code Online (Sandbox Code Playgroud)

首先我们find只在当前目录中查看,然后我们通过使用! -type d finally 我们执行sh并将所有内容移动到目标目录来忽略目录。您可能会{} +在最后尝试 ,这会更快。

  • @val0x00ff:“……上面的代码几乎与使用的任何 `find` 或 shell 兼容。” 是的,但 `find ... -exec mv {} MYDIR \;` 也是如此,它使用的资源比 `... -exec sh -c 'mv "$@" MYDIR' _ {} \;` 少。 (3认同)

小智 7

这可能有点危险,但是

cp * destination/
rm *
Run Code Online (Sandbox Code Playgroud)

因为 cp 和 rm 都无法在没有 -r 开关的目录上运行。

  • 聪明,但肯定生活在边缘 (7认同)
  • 这有几个问题:(1)它复制文件数据,因此如果“destination”位于同一文件系统上,那么它的效率将比仅进行重命名的“mv”低很多。(2) 如果存在以“-”开头的文件名(或者会产生不良后果,例如考虑“-t..”文件),则失败。(3) 对于符号链接,它会复制目标(假设它是一个目录)符号链接。(4) 它不保留元数据 (5) 它破坏硬链接...... (2认同)