Ran*_*ook 174 command-line bash
我正在将我的主目录从旧系统迁移到新系统,我制作的 tarball 包含所有内容,包括像 .bashrc 这样的隐藏文件。但是,当我将解压缩的 tarball(位于 /tmp 中)的内容移动到我的新主目录时,隐藏文件不会复制 ( mv /tmp/home/rcook/* /home/rcook/
)。我怎样才能让 mv 移动它们?
实际上,我认为问题不在于 mv,而在于 bash 的 globbing。如果我这样做:
mkdir a
mkdir b
touch a/.foo
touch a/bar
mv a/* b/
ls -a a/ b/
Run Code Online (Sandbox Code Playgroud)
我看到这个:
a/:
. .. .foo
b/:
. .. bar
Run Code Online (Sandbox Code Playgroud)
a/.foo
没动。那么如何获取 * 通配符来查找隐藏文件呢?
是的,我想我可以直接解压缩包到我的主目录,但将压缩包解压缩到home/rcook/...
了,我要确保我覆盖新.bashrc
等与旧,定制版本,并知道如何查找和移动隐藏文件是一项有价值的技能。建议?
一些答案建议做类似的事情mv src/.* dest/
。但是,我在我的测试目录上尝试了这个并出现了错误。从...开始:
rcook$ ls -a a/ b/
a/:
. .. bar .foo
b/:
. ..
rcook$ mv a/.* b/
mv: cannot move 'a/.' to 'b/.': Device or resource busy
mv: cannot remove 'a/..': Is a directory
rcook$ ls -a a/ b/
a/:
. .. bar
b/:
. .. .foo
Run Code Online (Sandbox Code Playgroud)
我究竟做错了什么?
Gil*_*not 185
你可以这样做 :
shopt -s dotglob
mv /tmp/home/rcook/* /home/rcook/
Run Code Online (Sandbox Code Playgroud)
你可以放
shopt -s dotglob
Run Code Online (Sandbox Code Playgroud)
~/.bashrc
如果您希望它成为默认值,则在您的。
见http://mywiki.wooledge.org/glob
复制点文件的另一种方法:
mv /tmp/home/rcook/.[!.]* /home/rcook/
Run Code Online (Sandbox Code Playgroud)
不要使用..*
匹配的模式..
(指向父目录的指针)。如果存在名称以两个点 ( ..something
)开头的文件,也使用模式..?*
.
小智 58
在您添加的内容中,您遇到了错误,但代码仍然有效。要添加的唯一的事情是,你告诉它只是复制点文件。尝试:
mv src/* src/.* dst/
Run Code Online (Sandbox Code Playgroud)
您仍然会收到 . 和 .. 条目,这很好。但此举应该会成功。
~/scratch [andrew] $ mv from/* from/.* to/
mv: cannot move ‘from/.’ to ‘to/.’: Device or resource busy
mv: cannot remove ‘from/..’: Is a directory
~/scratch [andrew] $ ls -a from/ to/
from/:
. ..
to/:
. .. test .test
Run Code Online (Sandbox Code Playgroud)
Aza*_*mat 14
如果您ls -l
在一个目录中,您将看到.
和..
列出的文件。所以,我认为mv .* /dest
考虑到这些指针。尝试:
mv /tmp/home/rcook/{*,.[^.]*,..?*} /home/rcook/
Run Code Online (Sandbox Code Playgroud)
这将忽略那些当前和父目录指针。
如果三个模式中的任何一个*
,[^.]*
或者不..?*
匹配任何文件,你都会得到一个错误,所以你应该只包含匹配的那些。
tca*_*arv 10
我知道这很旧,但是,一种简单的方法是:
mv a/{.*,*} b/
Run Code Online (Sandbox Code Playgroud)
这称为大括号扩展。在这种情况下,shell 通过连接大括号之前给出的字符串(在本例中为a/
)和大括号包围的列表中给出的每个变体来扩展您给出的路径。变体列表由用逗号分隔的值组成,并再次用大括号括起来。因此,在本例中,我们有.*
和*
作为元素,因此列表必须是{.*,*}
。
mv a/{.*,*} b/
Run Code Online (Sandbox Code Playgroud)
上面的表达式可以这样理解:将目录中以点 ( .*
)开头的所有文件以及其他任何内容 ( *
)移动a/
到该b/
目录。
这非常有帮助,可以在各种场景中使用。例如,假设您必须使用以下命名模式创建 100 个文件:file1、file2、file3...file100。通过这样做你可以轻松实现它
touch file{1..100}
Run Code Online (Sandbox Code Playgroud)
在本例中,您可以看到给出了一个范围。您可以通过用两个点 ( ..
) 分隔第一个值和最后一个值来实现此目的。
我是 Unix 世界的新手,即使知道它可以在bash
和zsh
(我到目前为止使用过的 shell)中工作,我也不能保证它可以在任何 shell 中工作。
您可以在 shell 文档中查看有关扩展和通配符的man bash
更多信息(分别使用:或man zshall
,分别表示 bash 和 zsh)。
希望这对未来的读者有所帮助!
我能想到的两种可能的解决方案。第一种是使用 cp 代替其递归选项,将当前目录复制到目标。
cp -Rp . /desired/directory
Run Code Online (Sandbox Code Playgroud)
然后你可以删除当前目录中的源文件
或者,如果您知道文件的名称很合理(没有空格、通配符、不可打印的字符),您可以执行以下操作
mv $(ls -A) /desired/directory
Run Code Online (Sandbox Code Playgroud)
Linux 上并不存在真正的“隐藏”文件。默认情况下,以点开头的文件在文件列表中隐藏。
要复制带有 glob 的文件,您需要在文件前添加前缀.
,mv -u .* foo
然后.foo
将显示为foo/.foo
移动时的样子。
-u 选项仅在源较新或目标丢失时才移动文件。或者您可以忽略有关移动的错误,因为它们是特殊文件.
并且..
无法移动,但确实会.*
被 shell 捕获在 glob 中。