我想备份我~/.ssh/id_rsa
的id_rsa.old
,但看起来它被删除了!这怎么可能? :)
root@localhost:~/.ssh# ls -l
total 16
-rw------- 1 root root 3326 Mar 12 11:22 id_rsa
-rw-r--r-- 1 root root 756 Mar 12 11:22 id_rsa.pub
-rw------- 1 userx userx 666 Mar 8 11:09 known_hosts
-rw-r--r-- 1 userx userx 666 Feb 29 10:53 known_hosts.old
root@localhost:~/.ssh# mv id_rsa *.old
root@localhost:~/.ssh# ls -l
total 12
-rw-r--r-- 1 root root 756 Mar 12 11:22 id_rsa.pub
-rw------- 1 userx userx 666 Mar 8 11:09 known_hosts
-rw------- 1 root root 3326 Mar 12 11:22 known_hosts.old
root@localhost:~/.ssh# touch p
root@localhost:~/.ssh# mv p *.p
root@localhost:~/.ssh# ls -l
total 12
-rw-r--r-- 1 root root 756 Mar 12 11:22 id_rsa.pub
-rw------- 1 userx userx 666 Mar 8 11:09 known_hosts
-rw------- 1 root root 3326 Mar 12 11:22 known_hosts.old
-rw-r--r-- 1 root root 0 Mar 12 11:28 *.p
root@localhost:~/.ssh# rm *.p
root@localhost:~/.ssh# ls -l
total 12
-rw-r--r-- 1 root root 756 Mar 12 11:22 id_rsa.pub
-rw------- 1 userx userx 666 Mar 8 11:09 known_hosts
-rw------- 1 root root 3326 Mar 12 11:22 known_hosts.old
userx@localhost:~$ uname -r
4.2.0-30-generic
userx@localhost:~$ lsb_release -a
No LSB modules are available.
Distributor ID: Ubuntu
Description: Ubuntu 15.10
Release: 15.10
Codename: wily
userx@localhost:~$ bash --version
GNU bash, version 4.3.42(1)-release (x86_64-pc-linux-gnu)
答案1
它已被重命名为known_hosts.old
,因此覆盖了以前的内容known_hosts.old
。
由于您已经在其中命名了一个文件known_hosts.old
,因此 glob 模式*.old
已扩展为known_hosts.old
.
简而言之,如下:
mv id_rsa *.old
已扩展为:
mv id_rsa known_hosts.old
在 中bash
,如果那里没有名为的文件known_hosts.old
,它将扩展为文字*.old
(假设您尚未启用nullglob
)。
答案2
看起来您认为mv id_rsa *.old
会移动id_rsa
到id_rsa.old
,并由*
第一个参数替换,但事实并非如此。通配符由 shell 扩展,而不是由命令扩展。当mv
看到该命令时,shell 已经扩展了通配符。有四种情况:
- 通配符模式不匹配任何文件。对于大多数 shell,这会使通配符模式未展开,因此
mv
使用参数id_rsa
和进行调用*.old
。然后它移动id_rsa
到一个名为*.old
(星号是文件名的第一个字符)的文件。在这种情况下,某些 shell(取决于其配置)将显示错误并且不运行命令。 - 通配符模式恰好匹配一个不是目录的文件。在这种情况下,shell 将用匹配文件的名称替换模式。因此
mv
移动id_rsa
到那个匹配的文件,覆盖以前的文件。这就是您的情况发生的情况:mv
使用参数id_rsa
和来调用known_hosts.old
,以known_hosts.old
被覆盖。 - 通配符模式匹配两个或多个文件,最后一个(按字典顺序)不是目录。在这种情况下,
mv
抱怨,因为除了最后一个文件之外的所有文件都是源文件,将多个文件移动到同一个文件上是没有意义的。 - 通配符模式匹配一个或多个文件,最后一个匹配(按字典顺序)是一个目录。源文件将移至该目录中。如果已经存在同名文件,则会覆盖该文件。如果模式有多个匹配项,则这也适用于除最后一个之外的与该模式匹配的所有文件,因为将
mv
它们视为源文件。
为避免mv
意外覆盖目标文件,请提示确认。将其放入 shell 初始化中(例如.bashrc
):
alias cp='cp -i'
alias mv='mv -i'
仅根据现有名称重命名文件mv
是无济于事的。您需要使用其他工具,或安排提供mv
完整的目标名称。执行您尝试执行的操作的一种方法是使用大括号扩展,它允许您指定具有共同词干的单词。
mv id_rsa{,.old}
shell 将其扩展为mv
参数id_rsa
(id_rsa
与空字符串连接)和id_rsa.old
(id_rsa
与 连接.old
)。
要根据模式批量重命名文件,最常用的工具是zmv
(仅限 zsh),prename
和mmv
。要将所有格式为 的文件重命名为,您可以使用id_SOMETHING
id_SOMETHING.old
zmv 'id_*' '$f.old'
mmv 'id_*' 'id_#1.old'
prename 's/$//' id_*