更改文件名后缀(使用 sed ?)

问题描述 投票:0回答:2

我想从文件中更改文件名后缀(使用bash脚本),但有时文件有一个句点,有些文件有两个。

现在我用这个:

new_file=`echo ${file} | sed 's/\(.*\.log.*\)'${suf}'/\1.'${num}'/'`

其中“new_file”是新文件名,“file”是原始文件名,“${suf}”是文件后缀,${num} 是新数字。

所以 some.log 必须变成 some.log.1some.log.1 必须变成 some.log.2。使用我的代码 some.log 变为 some.log.1,但是 some.log.1 仍然是 some.log.1.

希望我说得够清楚。我感谢任何建议(即使不使用 sed)。

更新:

@paxdiablo。我认为测试出了问题。

现在我用这段代码做测试;

#!/usr/bin/bash

        shft() {
            for suff in {6..1} ; do
                if [[ -f "$1.${suff}" ]] ; then
                    ((nxt = suff + 1))
                    echo Moving "$1.${suff}" to "$1.${nxt}"
                    mv -f "$1.${suff}" "$1.${nxt}"
                fi
            done
            echo Moving "$1" to "$1.1"
            mv -f "$1" "$1.1"
        }

        clear

        folder=~/logs/*.log

        for i in {1..20}; do
            echo ${i}> ~/logs/some.log 

            for fspec in ${folder} ; do
                    shft "${fspec}"
            done
        done

现在一切正常。抱歉造成混淆。

shell sed filenames rename
2个回答
5
投票

如果您想滚动日志文件,并且取决于您需要获得的复杂程度,我之前使用过以下部分:

#!/usr/bin/bash
# rollover.sh
#   Rolls over log files in the current directory.
#     *.log.8 -> *.log.9
#     *.log.7 -> *.log.8
#     : : :
#     *.log.1 -> *.log.2
#     *.log   -> *.log.1

shft() {
    # Change this '8' to one less than your desired maximum rollover file.
    # Must be in reverse order for renames to work (n..1, not 1..n).
    for suff in {8..1} ; do
        if [[ -f "$1.${suff}" ]] ; then
            ((nxt = suff + 1))
            echo Moving "$1.${suff}" to "$1.${nxt}"
            mv -f "$1.${suff}" "$1.${nxt}"
        fi
    done
    echo Moving "$1" to "$1.1"
    mv -f "$1" "$1.1"
}

for fspec in *.log ; do
    shft "${fspec}"
    #date >"${fspec}" #DEBUG code
done

这将自动将日志文件更新到版本 9,尽管您可以更改

suff
for
循环以允许更多版本。

添加了

DEBUG
以便自动创建新文件以进行测试,以下成绩单显示了它的运行情况:

pax> touch qq.log ; ./rollover.sh
Moving "qq.log" to "qq.log.1"

pax> touch "has spaces.log" ; ./rollover.sh
Moving "has spaces.log" to "has spaces.log.1"
Moving "qq.log.1" to "qq.log.2"
Moving "qq.log" to "qq.log.1"

pax> ll *log*
-rw-r--r-- 1 pax None 30 2010-09-11 20:39 has spaces.log
-rw-r--r-- 1 pax None  0 2010-09-11 20:39 has spaces.log.1
-rw-r--r-- 1 pax None 30 2010-09-11 20:39 qq.log
-rw-r--r-- 1 pax None 30 2010-09-11 20:38 qq.log.1
-rw-r--r-- 1 pax None  0 2010-09-11 20:38 qq.log.2

这个脚本的好处是它很容易配置以处理大量历史记录(通过更改

{8..1}
位),处理带有空格的名称,并且如果日志文件丢失,则相对稳健地处理间隙。


2
投票

要旋转日志,你真的应该使用 logrotate

如果你不能依赖 logrotate 可用,这里有一种方法可以在 shell 中实现。为了简单起见,我假设在脚本运行时没有其他任何东西(包括脚本的另一个实例)会尝试重命名日志文件。

最简单的方法是在实际将 log N 重命名为 N+1 之前递归重命名 log N+1。 shell 可以执行所有必要的算术运算,这里不需要

sed
。请注意,虽然递归函数在 POSIX shell 中是可能的,但除了位置参数之外没有局部变量(许多 shell 提供局部变量作为扩展)。

#!/bin/sh
## Move "$1.$2" to "$1.$(($2+1))", first rotating the target as well.
rotate () {
  if [ -e "$1.$(($2+1))" ]; then rotate "$1" $(($2+1)); fi
  mv -- "$1.$2" "$1.$(($2+1))"
}

for x; do
  ## Break each argument into FILE.NUMBER or just FILE.
  suffix=${x##*.}
  case $suffix in
    *[!0-9]*)
      if [ -e "$x.0" ]; then rotate "$x" 0; fi
      mv -- "$x" "$x.0";;
    *) rotate "${x%.*}" "$suffix";;
  esac
done

关于您所写的内容,请注意

echo ${file}
不好有两个原因:最重要的是,如果
${file}
包含任何特殊字符,例如空格,shell 将解释它们;此外,对于某些 shell,
echo
本身将解释反斜杠,并可能解释前导
-
。所以你应该总是写
printf %s "$file"

© www.soinside.com 2019 - 2024. All rights reserved.