目录中有一些文件、文件夹和点文件,如下所示
|-folder1
|----folder2
|----file.json
|----file2.php
|----.env
|----.dockerfile
|----.someconfig
|----.dockerignore
我运行命令mv $(ls | egrep -v '(.dockerfile|.env)') ../new_directory
将目录中的所有文件移动folder1
到new_directory
排除.dockerfile
和.env
,但实际上所有点文件都无法移动,为什么?
答案1
如果你跑
ls | egrep -v '(.dockerfile|.env)'
就其本身而言,您将了解这里发生的情况:输出将是
file2.php
file.json
folder2
发生这种情况是因为ls
默认情况下不列出点文件。要包含点文件,但不包含.
或..
,请使用ls -A
:
$ ls -A | egrep -v '(.dockerfile|.env)'
.dockerignore
file2.php
file.json
folder2
.someconfig
你不需要ls
在这里使用(并且你不应该),你可以使用 Bash 的扩展模式匹配:
shopt -s extglob dotglob
mv !(.dockerfile|.env|.|..) ../new_directory
这将匹配所有文件不是命名为.dockerfile
、.env
、.
或..
。使用这种方法,您不会遇到包含空格、换行符等的文件名的任何问题。
shopt -s extglob
启用扩展模式匹配,并shopt -s dotglob
允许 glob 匹配点文件。
答案2
你不应该用ls
这个。解析 的输出ls
往好了说是不可靠的,往坏了说是危险的。看为什么不是解析ls
(以及该怎么做)?
尝试find
一下。例如使用 GNU find
(和 GNU cp
):
find ./ -maxdepth 1 -regextype awk \
! -regex './(|\.env|\.dockerfile)' \
-exec echo cp -t ../new_directory/ {} +
我使用它是-regextype awk
因为我非常习惯 awk 中的正则表达式方言,并且我不想浪费时间弄清楚find-default
. -regextype egrep
也会同样有效。您可以通过运行获取可用方言列表find -regextype help
(不幸的是,PCRE 不是其中之一)。
排除、和。-regex ...
请注意,锚点和锚点都不是必需的,它们是隐式的's谓词,因此您只能得到精确匹配。如果您想要部分匹配,则必须添加到正则表达式的开头和/或结尾。这就是为什么我必须将 包含在正则表达式中。./
./env
./dockerfile
^
$
find
-regex
.*
./
如果我要从父目录运行它,则必须将其写为:
find folder1/ -maxdepth 1 -regextype awk \
! -regex 'folder1/(|\.env|\.dockerfile)' \
-exec echo cp -t ../newfolder {} +
或者使用与路径匹配的其他模式,例如'.*/(|\.env|\.dockerfile)'
.
这echo
使得这是一次演练,向您展示将复制哪些内容,而无需实际复制它们。当您确认该命令将执行您想要的操作后,将其删除。
GNUcp
的-t
选项允许您在要复制的文件列表之前指定目标目录。