我对 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
003
010
011
-
_
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)。