提取旧数字

提取旧数字

我对 Bash 脚本还很陌生,希望有人能帮助我。

我有一些包含图像的文件夹,其名称如下:

file_001.jpeg  
file_002.jpeg  
file_003.jpeg  

我正在尝试编写一个接受两个参数并重命名文件的 bash 函数,如下所示:

photo-argument1-argument2_001.jpeg  

例如

photo-christmas-2014_001.jpeg  

以下是我所拥有的:

function rename () {
  title="photo"
  h="-"
  u="_"
  new=$title$h$1$h$2$u
  for file in *.jpeg; do
    mv -v "$file" "$new"
  done
}

例如,运行rename birthday 2015就会产生photo-birthday-2015_

只有一个问题 - 我该如何将数字附加到新文件名中?就结果而言,从文件名中提取现有数字或生成新数字都可以,但哪种方法更好/更简单?我该如何实现这一点?

答案1

你可以通过告诉 bash 从哪里开始来让它为你计数,就像这样:

$ n=0
$ echo $((++n))
1
$ echo $((++n))
2
$ echo $((++n))
3

您可以使用来格式化和等的printf %03d结果,以实现更准确的排序。此外,没有必要将和设置为变量,因为它们不会改变。您的函数可能是这样的:$((++n))001 002 003010011-_

function rename () {
  title="photo"
  n=0
  for file in *.jpeg; do
   printf -v new "$title-$1-$2_%03d.jpeg" "$((++n))"
   mv -v -- "$file" "$new"
  done
}

其作用是:

$ rename birthday 2015
'file_001.jpeg' -> 'photo-birthday-2015_001.jpeg'
'file_002.jpeg' -> 'photo-birthday-2015_002.jpeg'
'file_003.jpeg' -> 'photo-birthday-2015_003.jpeg'

但是 Ubuntu 中已经有一个有用的rename命令,因此您可能想使用不同的名称:)

答案2

稍微长一点但可用的 Python 替代方案。假设您的命名与示例中的命名一致,您可以在您的 中使用此功能~/.bashrc。(请注意“\”字符。之后不能有空格,只能有换行符)

rename_photos()
{
    python -c 'import os,re,sys; \
    [ os.rename(f, "photo_"+sys.argv[1]+\
      "_"+sys.argv[2]+"_"+re.split("[_.]",f)[-2]+\
      "."+re.split("[_.]",f)[-1])  \
      for f in os.listdir(".") \
    ]' "$1" "$2"
}

并调用类似

rename_photos arg1 arg2

假设你的命名是一致的,它的作用是将文件名拆分为“。”和“_”部分,并通过os.rename 函数重命名它们

例如:

$ ls
file_001.jpeg  file_002.jpeg  file_003.jpeg
$ rename_photos birthday 2016
$ ls
photo_birthday_2016_001.jpeg  photo_birthday_2016_002.jpeg  photo_birthday_2016_003.jpeg

脚本版本

不必太复杂,这里有一个可以执行相同功能的小脚本。有很多注释来解释每个部分的作用。脚本本身必须存储在属于变量的目录之一中$PATH,例如~/bin文件夹中。否则,它会执行完全相同的功能(除了打印新文件名之外)

#!/usr/bin/env python
import os
import re
import sys

# The operates on all files in the current working
# directory, so you would have to cd to your folder
# and run script there. 
for item in os.listdir("."):

    # We don't wanna rename the script itself ( just in case ) and
    # we don't
    if os.path.join("./" + item) != __file__ and \
       os.path.isfile("./" + item):
           title="photo_"

           # Old name can be split into parts using _ and . as 
           # separators, so we only take items between those as one.
           # The last item (-1) is extension, and the one
           # before extension is number
           old_name = re.split("[_.]",item)
           new_name = sys.argv[1] + sys.argv[2] + "_" \
                      + old_name[-2] + "." + old_name[-1]

           print(new_name)
           os.rename(item,new_name)

答案3

我的理解是,你只需要在末尾添加连续的数字。我个人会这样做

 function rename () {
  count=1           #The first photo will get number 1 to the end
  title="photo"
  h="-"
  u="_"
  new=$title$h$1$h$2$u
  for file in *.jpeg; do
    if [ $count -lt 10 ]; then
        mv -v "$file" "${new}00$count" #numbers 1-9 will be like 001 002..
    elif [ $count -lt 100 ]; then
        mv -v "$file" "${new}0$count" #numbers 10-99 like 022 056 etc..
    else
        mv -v "$file" "$new$count"
    fi
    count=$[ $count + 1 ]      #count variable gets bigger by one 
  done
}

重命名文件时,它们将获得连续的数字,并在末尾添加填充。这可以按照其他答案中所示以不同的方式完成,但我发现如果一个人对 bash 脚本不太了解,这很容易理解

希望这可以帮助!

答案4

您可以自行决定哪种方法更简单。

提取旧数字

您可以使用 grep 之类的命令获取文件名中的数字:

number=$(egrep -o '[0-9]+' <<< "$file")

上述命令将变量文件(通过传递给 grep)中的任何数字序列(由模式 '[0-9]+' 匹配)保存 <<<到变量数字中。

生成新数字

您可以尝试以下操作:

number=0 # initialize number to 0
for file in *.jpeg; do
    ... # do some stuff here
    ((number+=1)) # adds 1 to the variable number
done

这将为您的每个文件生成一个从 0 开始的数字。

为了排序,将数字格式化为固定宽度(即 001 而不是 1)可能很有用。在这种情况下,您可以使用 printf 获得所需的输出:

number_formatted="$(printf "%03d" "$number")"

上述代码将“12”格式化为“012”,将“321”格式化为“321”。“%03d”指定格式(0 表示在数字前面添加 0,3 指定打印总共 3 位数字,包括任何 0)。

相关内容