你要找的命令是
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
的参数。
简答:使用
find . -mindepth 1 -maxdepth 1 -exec mv -t.. -- {} +
长答。
mv * .* ..
命令
将不起作用,因为.*
可以匹配.
和..
。但是命令
mv * .[^.]* ..
也不行,因为.[^.]*
不会匹配,比如,..filename
!相反,我所做的是
mv * .[^.] .??* ..
会匹配除了.
和..
以外的所有东西。*
将匹配所有不以.
开头的文件,.[^.]
将匹配除..
以外所有以点开头的2个字符的文件名,而.??*
将匹配所有以点开头至少3个字符的文件名。
更好的是,你可以使用
find . -mindepth 1 -maxdepth 1 -exec mv -t.. -- {} +
,这样可以避免mv * .[^.] .??* ..
中丑陋的glob黑客!
当使用*
时,mv缺乏移动隐藏文件的功能–那么为什么不使用copy来代替呢?
cp -rf . ..
rm -rf *
不需要进入复杂的dotglobbing解决方案和使用find命令。
这个最小化命令适用于大多数现代的shell:
\mv -- {,.{[^.],??}}* ..
其他提到的是一个便携式解决方案。
\mv -- * .[^.] .??* ..
特点:
\ 防止别名对mv造成不良影响。
– 防止包含前导连字符(-xyz)的文件名被解释为命令行参数。
.[^.]匹配所有以.开头的两个字符的文件名,除了.。
.??/*匹配所有其他三个字符或更长的文件名。
天真的实现:
1.下面跳过隐藏的UNIX文件名,那些以.开头的文件名。(.bashrc)开头的文件名。
最终尝试mv .
会失败,因为mv无法解除你当前所在的目录的链接。你可以mv * ..
来移动cwd中的文件。
使用* .[!.] .??*
模式比* .[^.] .??*
模式更正确,因为前者也适用于较老的shell,如ksh88。
mv -- * .[!.] .??* ..
--
可以防止以-
开头的文件名出现问题 - *
可以匹配所有不是以.
开头的文件名 - 没有以.
开头的单一字符文件名,你可以/应该移动
。.[!.]
匹配所有两个以 .
开头的字符文件名 - .??*
匹配所有三个以 .
开头的字符文件名(或更长)。文件名模式.[^.]
实际上会匹配文件名..
(一直存在)和.^
(可能不存在),产生了与期望相反的效果。
mv * .??* ../.
*
获取所有非点文件。.??*
获取所有至少三个字节长的 .文件,这对所有合法的文件都有效。剩下的任何文件你可能都想用rm
而不是mv
。
../.
并没有比..
提供任何直接的好处,但是在进行移动到目录的时候,这是一个非常好的习惯,因为如果路径有问题,它就会失败,如你所愿。例如,mv xyz bletch
,你_认为bletch
是一个目录,可以用mv xyz bletch/.
更加确定。
查找和grep也可以。如果你想通过修改find和egrep来选择更复杂的标准的文件,这种结构可能会有帮助。
find -maxdepth 1 | egrep '^./.' # Returns all files
mv `find -maxdepth 1 | egrep '^./.'` .. # mv <all files> ..
我认为最简单的解决方案是将所有文件移动到它的父目录下,使用
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
。