12.04 和 16.04 中 cp 命令对星号的处理方式不同

wht*_*ger 2 bash

为了在 12.04 中备份配置文件,我使用了以下语法:

cp -p fstab *.bak
Run Code Online (Sandbox Code Playgroud)

这没有问题,文件fstab.bak是在与原始文件相同属性的同一文件夹中创建的。
在 16.04 中,此命令的工作方式完全不同。它*.bak改为创建文件,即原始文件的副本,名称为 asterisk-dot-bak。如果bak此文件夹中已存在具有扩展名的文件,则它不执行任何操作并发出警告:

cp: 目标 'inputrc.bak' 不是目录

我认为 globbing 在 12.04 和 16.04 中的工作方式不同。我比较shopt了两个系统的输出 - 差异很小,通配选项相同。ORcp在 16.04 中处理星号的方式与在 12.04 中不同。
有没有办法cp在 16.04 中保留命令的旧行为?

mur*_*uru 25

这不是全局错误的情况,而是目录中存在哪些文件:

  1. 没有.bak文件存在。然后*.bak,除非nullglob设置,扩展为*.bak。所以命令 run 是字面意思cp -p fstab *.bak
  2. 只是fstab.bak在场。然后*.bak将扩展到 justfstab.bakcp -p fstab fstab.bak运行。无论是否存在文件,这似乎都是您所期望的。
  3. *.bak存在多个文件(例如,fstab.bakinputrc.bak)。所以,cp -p fstab fstab.bak inputrc.bak是运行。在这种情况下,cp期望最后一个参数是一个目录,或者使用-t. 如果没有,它会抱怨。

不要做愚蠢的事情,例如cp file *.bak,其结果可能会因存在的文件而异。如果不存在并且是,您真的希望fstab得到支持吗?如果您懒得输入文件名,请使用大括号扩展:iputrc.bakfstab.bakinputrc.bak

cp -p file{,.bak}
Run Code Online (Sandbox Code Playgroud)

更好的是,使用版本控制和etckeeper而不是脆弱的.bak复制。

  • @whtyger:冒着重复穆鲁所说的一切的风险,强调一下:`cp -p fstab *.bak` 是一个糟糕的命令。穆鲁称之为“愚蠢”;我会称它为危险的,因为它很有可能做一些你想做的事情,可能是有害的。(举个muru没有提到的例子,`cp passwd *.bak && cp group *.bak`可以复制你的`passwd`文件*称为`*.bak`,**然后覆盖它** * 带有您的`group` 文件的副本。)它*从不* 像您想象的那样工作。在 `cp -p fstab *.bak` 第一次工作之前,你*必须**已经*有一个 `fstab.bak` 文件。 (5认同)