2009-10-28 18:54:06 +0000 2009-10-28 18:54:06 +0000
134
134

如何将当前目录下的所有文件移动到上层目录?

如何在linux中把所有文件从当前目录移到上层目录?

我试过类似mv *.*的东西,但没有用。

答案 (11)

204
204
204
2009-10-28 19:01:58 +0000

你要找的命令是

mv * .[^.]* ..

或 (更多信息见下文):

(shopt -s dotglob; mv -- * ..)

解释: mv 命令会移动文件和目录。mv的最后一个参数是目标(在本例中,是树上 “上 "一步的目录,..)。之前的参数是源文件和目录。星号 (*) 是一个通配符,它匹配所有不以点开始的文件。以点号开头的文件(dotfiles)是 "隐藏 "的。它们使用.[^.]*模式进行匹配(见下面的编辑)。

更多关于 mv 的信息请参见我链接的 manpage。


为什么用 .[^.]* 而不是 .* ?

正如 Chris Johnsen 正确地指出:.* 的模式也与 ... 相匹配。因为你不想(也不能)移动这些文件,所以最好使用一个匹配任何以点开头的文件名的模式除了这两个。模式 .[^.]* 就是这样做的:它匹配任何文件名 (1) 以点开始 (2) 后面跟着一个不是点的字符 (3) 后面跟着零个或多个任意字符。

正如 Paggas 指出 ,我们还必须添加模式 .??* 来匹配以两个点开始的文件。参见他的回答,以获得使用find的另一种解决方案。

Arjan 的 答案 提到了 shopt ,以避免所有这些点文件的问题。但还是有以破折号开头的文件的问题。而且它需要三个命令。不过,我还是喜欢这个想法。我建议这样使用。

(shopt -s dotglob; mv -- * ..)

这将在一个子壳中执行shopt(因此不需要第二次调用shopt),并使用--,这样以破折号开头的文件就不会被解释为mv的参数。

45
45
45
2009-10-28 20:19:07 +0000

简答:使用

find . -mindepth 1 -maxdepth 1 -exec mv -t.. -- {} +

长答。

mv * .* ..

命令

将不起作用,因为.*可以匹配...。但是命令

mv * .[^.]* ..

也不行,因为.[^.]*不会匹配,比如,..filename!相反,我所做的是

mv * .[^.] .??* ..

会匹配除了...以外的所有东西。*将匹配所有不以.开头的文件,.[^.]将匹配除..以外所有以点开头的2个字符的文件名,而.??*将匹配所有以点开头至少3个字符的文件名。

更好的是,你可以使用

find . -mindepth 1 -maxdepth 1 -exec mv -t.. -- {} +

,这样可以避免mv * .[^.] .??* ..中丑陋的glob黑客!

14
14
14
2009-10-28 20:52:27 +0000

为了完整起见,还可以告诉Bash shell包含隐藏文件,使用 shopt :

shopt -s dotglob
mv -- * ..
shopt -u dotglob
8
8
8
2011-08-02 20:46:48 +0000

当使用*时,mv缺乏移动隐藏文件的功能–那么为什么不使用copy来代替呢?

cp -rf . ..

rm -rf *

不需要进入复杂的dotglobbing解决方案和使用find命令。

7
7
7
2013-01-20 11:47:53 +0000
rsync -a --remove-source-files . ..

rsync 是一个非常强大的文件复制工具,一般用于执行高效的增量式远程备份和镜像。

通过上面的命令,我们是告诉rsync.的内容复制到..

开关-a启用递归到.子目录,并启用其他一些常用选项。

开关--remove-source-files告诉rsync在复制成功后删除源文件,即让rsync的行为与mv命令类似。

2
2
2
2011-08-12 08:12:49 +0000

这个最小化命令适用于大多数现代的shell:

\mv -- {,.{[^.],??}}* ..

其他提到的是一个便携式解决方案。

\mv -- * .[^.] .??* ..

特点:

  1. \ 防止别名对mv造成不良影响。

  2. – 防止包含前导连字符(-xyz)的文件名被解释为命令行参数。

  3. .[^.]匹配所有以.开头的两个字符的文件名,除了.。

  4. .??/*匹配所有其他三个字符或更长的文件名。

天真的实现:

1.下面跳过隐藏的UNIX文件名,那些以.开头的文件名。(.bashrc)开头的文件名。

  1. 下面匹配的是……,它递归地试图将每个目录最终全部移回/到当前工作目录($PWD或pwd)的……。永远不使用.
2
2
2
2009-10-28 18:59:46 +0000

最终尝试mv .会失败,因为mv无法解除你当前所在的目录的链接。你可以mv * ..来移动cwd中的文件。

2
2
2
2013-10-22 22:24:11 +0000

使用* .[!.] .??*模式比* .[^.] .??*模式更正确,因为前者也适用于较老的shell,如ksh88。

mv -- * .[!.] .??* ..
  • --可以防止以- 开头的文件名出现问题 - *可以匹配所有不是以. 开头的文件名 - 没有以.开头的单一字符文件名,你可以/应该移动 。.[!.] 匹配所有两个以 . 开头的字符文件名 - .??* 匹配所有三个以 .

开头的字符文件名(或更长)。文件名模式.[^.]实际上会匹配文件名..(一直存在)和.^(可能不存在),产生了与期望相反的效果。

2
2
2
2009-10-28 19:47:28 +0000
mv * .??* ../.

*获取所有非点文件。.??* 获取所有至少三个字节长的 .文件,这对所有合法的文件都有效。剩下的任何文件你可能都想用rm而不是mv

../.并没有比..提供任何直接的好处,但是在进行移动到目录的时候,这是一个非常好的习惯,因为如果路径有问题,它就会失败,如你所愿。例如,mv xyz bletch,你_认为bletch是一个目录,可以用mv xyz bletch/.更加确定。

0
0
0
2014-05-12 23:08:11 +0000

查找和grep也可以。如果你想通过修改find和egrep来选择更复杂的标准的文件,这种结构可能会有帮助。

find -maxdepth 1 | egrep '^./.' # Returns all files

mv `find -maxdepth 1 | egrep '^./.'` .. # mv <all files> ..
0
0
0
2014-08-06 16:37:16 +0000

我认为最简单的解决方案是将所有文件移动到它的父目录下,使用

mv "`ls`" ../

或者,如果有隐藏的文件/目录

使用。

mv "`ls -a`" ../ 2>/dev/null

另外,假设你想把某个文件夹的内容移动到它的内部文件夹tony(比如)

使用:

mv "`ls -a`" /tony 2>/dev/null

注意:

"`ls -a`"

要移动其中有空格的文件。

2>/dev/null

是用来抑制警告/错误的,因为ls -a会把...文件夹也打印出来,你无法移动或复制它们。所以对于这些文件夹,它会显示错误(如果我们不使用2/>/dev/null),它不能移动它们,其余的文件夹会被很舒服地移动。

如果没有隐藏文件,最好避免使用ls -a,而只使用ls