我有一台虚拟机,它运行着我们的主要应用程序之一。在进行相当大范围的更改之前,我做了两行备份。首先,我拍摄了虚拟机快照。其次,我sed
在整个系统中运行了一个递归命令来替换文件中的文本,并在执行过程中创建备份。直到运行完这个命令后,我才意识到更改的范围有多大。以下是我运行的内容:
find / -type f -print0|xargs -0 sed -i.matthew05012013 's/oldtext/newtext/g'
我尝试恢复快照,但最终却删除了它,这提交了所有更改(因为 ESX 命名法与快照非常混乱)。因此,我的最后一道防线是递归地检查系统,并将任何带有 .matthew05012013 扩展名的内容重命名为相同的文件名,而不使用扩展名,覆盖其中的所有内容。
有人知道如何最好地执行此操作吗?手动操作不行,整个系统中有几千个文件被修改了。
答案1
虽然不太优雅,但下面的方法应该可以解决问题:
for modfile in `find <dir> -name "*.matthew05012013"`; do
realfile=`echo $modfile | sed 's/.matthew05012013//'`
cp $modfile $realfile
done
我对测试目录进行了此操作:
$ find /tmp/deleteme/
/tmp/deleteme/
/tmp/deleteme/1
/tmp/deleteme/1/filea
/tmp/deleteme/1/fileb
/tmp/deleteme/1/filec
/tmp/deleteme/1/filed
/tmp/deleteme/1/fileb.matthew05012013
/tmp/deleteme/1/filed.matthew05012013
/tmp/deleteme/2
/tmp/deleteme/2/filea
/tmp/deleteme/2/fileb
/tmp/deleteme/2/filec
/tmp/deleteme/2/filed
/tmp/deleteme/2/fileb.matthew05012013
/tmp/deleteme/2/filed.matthew05012013
/tmp/deleteme/3
/tmp/deleteme/3/filea
/tmp/deleteme/3/fileb
/tmp/deleteme/3/filec
/tmp/deleteme/3/filed
/tmp/deleteme/3/fileb.matthew05012013
/tmp/deleteme/3/filed.matthew05012013
/tmp/deleteme/4
/tmp/deleteme/4/filea
/tmp/deleteme/4/fileb
/tmp/deleteme/4/filec
/tmp/deleteme/4/filed
/tmp/deleteme/4/fileb.matthew05012013
/tmp/deleteme/4/filed.matthew05012013
/tmp/deleteme/5
/tmp/deleteme/5/filea
/tmp/deleteme/5/fileb
/tmp/deleteme/5/filec
/tmp/deleteme/5/filed
/tmp/deleteme/5/fileb.matthew05012013
/tmp/deleteme/5/filed.matthew05012013
/tmp/deleteme/6
/tmp/deleteme/6/filea
/tmp/deleteme/6/fileb
/tmp/deleteme/6/filec
/tmp/deleteme/6/filed
/tmp/deleteme/6/fileb.matthew05012013
/tmp/deleteme/6/filed.matthew05012013
$ for modfile in `find /tmp/deleteme -name "*.matthew05012013"`; do
realfile=`echo $modfile | sed 's/.matthew05012013//'`
echo "cp $modfile $realfile"
done
cp /tmp/deleteme/1/fileb.matthew05012013 /tmp/deleteme/1/fileb
cp /tmp/deleteme/1/filed.matthew05012013 /tmp/deleteme/1/filed
cp /tmp/deleteme/2/fileb.matthew05012013 /tmp/deleteme/2/fileb
cp /tmp/deleteme/2/filed.matthew05012013 /tmp/deleteme/2/filed
cp /tmp/deleteme/3/fileb.matthew05012013 /tmp/deleteme/3/fileb
cp /tmp/deleteme/3/filed.matthew05012013 /tmp/deleteme/3/filed
cp /tmp/deleteme/4/fileb.matthew05012013 /tmp/deleteme/4/fileb
cp /tmp/deleteme/4/filed.matthew05012013 /tmp/deleteme/4/filed
cp /tmp/deleteme/5/fileb.matthew05012013 /tmp/deleteme/5/fileb
cp /tmp/deleteme/5/filed.matthew05012013 /tmp/deleteme/5/filed
cp /tmp/deleteme/6/fileb.matthew05012013 /tmp/deleteme/6/fileb
cp /tmp/deleteme/6/filed.matthew05012013 /tmp/deleteme/6/filed
显然,这和你之前提到的方法一样,如果我要在生产中这样做,我可能会回显 cp 命令(如我的测试所示)并将它们发送到文件进行审查。然后在我确认一切正常后执行它们。只需确保您查找的字符串(示例中为 .matthew05012013)足够独特,以至于它不会与其他内容匹配。并将“cp”替换为“mv”或任何其他您喜欢的命令。
我还建议在进行此更改之前再做一次快照,以防万一出现进一步的问题,您不必尝试清理额外的混乱。
在此更改期间还要注意保留权限。在执行此操作之前,请检查“cp”手册页以添加用于保留权限的参数或实现特定的 umask。当您有数千个文件的权限不允许您的应用程序正常运行时,您很快就会陷入困境。
答案2
find / -type f -name '*.matthew05012013' -print0 | \
xargs -0 rename .matthew05012013 ""
如果文件名称中出现两次“.matthew05012013”,且文件末尾出现一次,则此操作会失败。但情况可能并非如此,可以使用其他工具(如 mmv)或简单的 shell 脚本来避免这种情况。