为什么mv删除了mv id_rsa *.old的文件?

为什么mv删除了mv id_rsa *.old的文件?

我想备份我~/.ssh/id_rsaid_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_rsaid_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_rsaid_rsa与空字符串连接)和id_rsa.oldid_rsa与 连接.old)。

要根据模式批量重命名文件,最常用的工具是zmv(仅限 zsh),prenamemmv。要将所有格式为 的文件重命名为,您可以使用id_SOMETHINGid_SOMETHING.old

zmv 'id_*' '$f.old'
mmv 'id_*' 'id_#1.old'
prename 's/$//' id_*

相关内容