如何将所有文件(包括隐藏文件)从一个目录移动到另一个目录?

如何将所有文件(包括隐藏文件)从一个目录移动到另一个目录?

如何将一个目录中的所有文件(包括隐藏文件)移动到另一个目录?

例如,如果我有一个文件夹“Foo”,其中包含文件“.hidden”和“notHidden”,如何将这两个文件移动到名为“Bar”的目录?以下内容不起作用,因为“.hidden”文件保留在“Foo”中。

mv Foo/* Bar/

自己尝试一下。

mkdir Foo
mkdir Bar
touch Foo/.hidden
touch Foo/notHidden
mv Foo/* Bar/

答案1

先快速回答;有关 bash、ksh93 和 zsh 的更深入讨论和文档链接,请参阅下文。

兹什

mv Foo/*(DN) Bar/

或者

setopt glob_dots null_glob
mv Foo/* Bar/

选项名称中的大小写和下划线将被忽略。set -o也可以像在类似 Korn/POSIX 的 shell 中一样使用,并且dotglob还支持 (DotGlob、DOT_GLOB...) 以与 GNU shell (bash) 兼容。

重击

shopt -s dotglob nullglob
mv Foo/* Bar/

肯什93

如果您知道该目录不为空:

FIGNORE='.?(.)'
mv Foo/* Bar/

如果您知道该目录不为空:

mv Foo/{.,}* Bar/

标准 (POSIX) sh

for x in Foo/* Foo/.[!.]* Foo/..?*; do
  if [ -e "$x" ]; then mv -- "$x" Bar/; fi
done

如果您愿意让mv命令返回错误状态,即使它成功了,它也会简单得多:

mv Foo/* Foo/.[!.]* Foo/..?* Bar/

GNU find 和 GNU mv

find Foo/ -mindepth 1 -maxdepth 1 -exec mv -t Bar/ -- {} +

标准查找

find Foo/. ! -name . -prune -exec sh -c 'mv -- "$@" "$0"' ../Bar/ {} +

以下是有关控制点文件在 bash、ksh93 和 zsh 中是否匹配的更多详细信息。

重击

设置dotglob选项

$ echo *
none zero
$ shopt -s dotglob
$ echo *
..two .one none zero

还有更灵活的GLOBIGNORE多变的,您可以将其设置为要忽略的以冒号分隔的通配符模式列表。如果未设置(默认设置),则如果dotglob设置了该值,则 shell 的行为就像该值为空;如果.*未设置该选项,则 shell 的行为就像该值为空。看文件名扩展在手册中。普遍目录...总是被省略,除非.被模式显式匹配。

$ GLOBIGNORE='n*'
$ echo *
..two .one zero
$ echo .*
..two .one
$ unset GLOBIGNORE
$ echo .*
. .. ..two .one
$ GLOBIGNORE=.:..
$ echo .*
..two .one

肯什93

设置FIGNORE多变的。如果未设置(默认设置),shell 的行为就像该值为.*。要忽略...,必须显式匹配它们(ksh 93s+ 2008-01-31 中的手册指出...始终被忽略,但这不再正确描述实际行为;编辑 这是固定的,因为)。

$ echo *
none zero
$ FIGNORE='@(.|..)'
$ echo *
..two .one none zero
$ FIGNORE='n*'
$ echo *
. .. ..two .one zero

您可以将点文件包含在图案通过明确匹配它们。

$ unset FIGNORE
$ echo @(*|.[^.]*|..?*)
..two .one none zero

要在目录为空时使扩展为空,请使用N模式匹配选项:~(N)@(*|.[^.]*|..?*)~(N:*|.[^.]*|..?*)

兹什

设置dot_glob选项

% echo *
none zero
% setopt dot_glob
% echo *
..two .one none zero

...永远不会匹配,即使模式.显式匹配前导。

% echo .*
..two .one

您可以使用以下命令将点文件包含在特定模式中:D 全局限定符

% echo *(D)
..two .one none zero

添加Nglob 限定符以使扩展在空目录中显示为空:*(DN)


注意:根据、和变量的设置,您可能会以不同的顺序获得文件名扩展结果(例如,none后跟.one后跟) 。..twoLC_COLLATELC_ALLLANG

答案2

#!/bin/bash

shopt -s dotglob
mv Foo/* Bar/

man bash

点球如果设置,bash 包含以“.”开头的文件名在路径名扩展的结果中。

答案3

执行此操作的一个简单方法bash

mv {Foo/*,Foo/.*} Bar/

但这也会移动目录。

如果您想移动所有文件(包括隐藏文件)但不想移动任何目录,您可以使用 for 循环和测试。

for i in $(ls -d {Foo/*,Foo/.*});do test -f $i && mv -v $i Bar/; done;

答案4

我发现这对于 bash 很有效,并且不需要更改 shell 选项

mv sourcedir/{*,.[^.]*} destdir/

编辑:

因此,正如 G-man 所说,我最初的答案不符合 posix,并且与上面 ndemou 的答案几乎相同,但有一个更改,即使用大括号扩展来创建然后执行操作的字符串列表。这只是意味着您不需要cd进入源目录。确实变化不大,但确实有所不同。

示例:假设您已经有以下布局。

 $ tree -a
.
├── destdir
└── sourcedir
    ├── ..d1
    ├── ..d2
    ├── ..double
    ├── file-1
    ├── file-2
    ├── .hidden-1
    ├── .hidden-2
    ├── ...t1
    └── ...t2

最初的问题仅提到带有单个句点的隐藏文件,但假设有些文件名称开头有两个或多个句点。您只需在大括号中添加一个附加表达式即可。然后我们就可以执行

mv sourcedir/{*,.[!.]*,..?*} destdir/

这扩展到以下内容:

mv sourcedir/file-1 sourcedir/file-2 sourcedir/.hidden-1 sourcedir/.hidden-2 sourcedir/..d1 sourcedir/..d2 sourcedir/..double sourcedir/...t1 sourcedir/...t2 destdir/

您现在应该看到位于以下位置的所有文件目标目录:

 $ tree -a
.
├── destdir
│   ├── ..d1
│   ├── ..d2
│   ├── ..double
│   ├── file-1
│   ├── file-2
│   ├── .hidden-1
│   ├── .hidden-2
│   ├── ...t1
│   └── ...t2
└── sourcedir

您可以在 bash 中使用大括号做一些非常酷的事情,并且在 4.x 中添加了更多功能。查看bash黑客一些漂亮的例子。

相关内容