文件扩展名为 .bak _before_ 的备份文件

文件扩展名为 .bak _before_ 的备份文件

我通常在没有版本控制的服务器上备份配置文件,如下所示:

# cp httpd.conf{,.bak}
# ls
httpd.conf    httpd.conf.bak

但是,对于 Web 根目录中的文件,我会花时间仔细地将 放在.bak文件扩展名之前,以便.php保留 和 Apache 仍将通过 PHP 解释器发送文件(如果有人设法猜测或探测服务器中是否存在此类文件):

$ cp index.php index.bak.php
$ ls
index.php    index.bak.php

有没有办法使用制表符补全和肌肉记忆将 放在.bak文件扩展名之前?我已经Tab{}←,.bak记住了肌肉记忆,我无法在网络根目录中的文件上使用这个漂亮的“肉宏”。

谢谢。

答案1

可能很简单

cp file.{ext,bak.ext}

bash {} 扩展扩展为所有组合(与列出现有文件的 [] 扩展不同。因此它生成两个文件名。

{ .... , .... } 提供了两个选项,因此您可以获得 file.ext 和 file.bak.ext

在你的脚本中你会使用

cp $FILE.{$EXTENTION,bak.$EXTENTION}

要将 FILENAME 分成两半,您可以使用

FILE=${FILENAME%.*}
EXTN=${FILENAME##*.}

${VAR%xxxxx} 将返回 VAR 中内容的左侧直至匹配模式,在上面的情况下,模式为 .*,因此您将获得除最后一个 .* 之外的所有内容

${VAR##xxxxx} 将返回 VAR 中匹配模式之后内容的右侧。双哈希意味着获得最大可能的匹配,以防存在多个可能的匹配。

要保存脚本,请检查获取 FILE 和 EXTENTION 后是否存在不同的情况。如果文件名没有扩展名,就会发生这种情况。

脚本的一个子部分可能如下所示:

ls *html | while read FILENAME
do
    FILE=${FILENAME%.*}
    EXTN=${FILENAME##$FILE}
    cp $FILE{$EXTN,.bak$EXTN}
done

答案2

您始终可以使用一个函数:

backup()
  for i do
    case ${i##*/} in
      (?*.?*) cp -iv -- "$i" "${i%.*}.bak.${i##*.}";;
      (*) cp -iv -- "$i" "$i.bak"
    esac
  done

${i##*/}是 的基本名称$i(即删除了$i最右边的所有内容/),因为我们不想将bar/file其视为foo.bar/file.

然后我们检查是否$i包含扩展名,即是否至少包含一个dot两边都有字符的字符(?*任意一个字符其次是0 个或多个字符, 所以就是一个或多个字符)。例如,我们不能这样做*.*,否则我们会进行备份。~/.bashrc~/.bak.bashrc

上面的语法是 POSIX,除了-v(for冗长的) 选项cp是 GNU 扩展,也可以在 BSD 等其他一些实现中找到。

然后你可以做这样的事情:

backup foo.php bar.html baz<Tab>...

或者:

backup *.php

不必担心丢失数据(-i在覆盖文件之前会要求确认,另请参阅-bGNU 选项cp)或没有选择正确的名称。

答案3

我无法立即想出一种方法来完成制表符,除了可能还保留一份不带扩展名的文件名副本,这样您就可以一次性添加“bak.php”。但我的解决方案是一个小的 shell 脚本,它将文件名作为输入并将其复制到“firstpart.bak.extension”。

答案4

我在几个没有源代码控制的 UNIX 系统上遇到了这个问题,并且需要快速进行小的更改。对于这样的情况,我使用脚本来剪切文件,以剪切带有时间戳的副本,以便快速恢复。 ls 显示其后按文件名排序的版本日期的文件。

if [ "$1" = "" ]; then
   echo "File name required. Aborting."
   exit 1
fi

CDATE=`date +%Y-%m-%d-%H-%M`
cp "$1" "$1-$CDATE"
echo File backed up to: $1-$CDATE

用法:

VERS.sh httpd.conf

输出:

File backed up to: httpd.conf-2016-07-14-10-27

相关内容