假设我有这样的文件:
out-1.avi
我想要一段 bash 代码,它可以为我提供此类列表的下一个文件名:
out-1.avi
out-2.avi
out-3.avi
etc.
编辑我需要实现的是获取网络摄像头录制脚本的下一个文件名,这样它就不会覆盖!
答案1
我不知道上下文,但以下循环包含您需要的所有元素:-
n=0; while (($n < 10)); do ((++n)); echo name=out-$n.avi; done
这将列出序列中的前 10 个文件。
经过您的编辑,我看到了几个答案。
对原始循环进行简单修改如下:-
n=1; while [ -f out-$n.avi ]; do ((++n)); done; echo name=out-$n.avi
这对于少量文件来说会很有效,但是当文件数量增加到数百个时,它会变得越来越低效。
更有效的答案是将最新的文件编号保存在其自己的文件中:-
n=`line<avicount.text`; ((++n)); echo "$n">avicount.text; echo name=out-$n.avi
每次调用时,此脚本都会生成一个新名称,但依赖于avicount.text
始终与正在使用的文件和名称保持同步。
总体而言,更好的解决方案是使用时间戳而不是序列号:-
echo name=out-`date +%Y%M%d%H%m%S`.avi
这将根据脚本调用时的秒数给出一个唯一的名称,将文件的创建时间包含在其名称中会很有用。此方案还允许随意删除、存档或以其他方式移动文件,而不会影响将来的文件名。
答案2
您可以使用它seq
来生成值,然后touch
创建文件。
for n in $(seq 1 5)
do
touch out-${n}.avi
done
答案3
#!/bin/bash
LAST=$(find . -maxdepth 1 -name "*.avi" -type f -printf "%p\n" | sed -e s/.\\/out-//g -e s/.avi//g | sort -g | tail -1)
touch out-$(($LAST + 1)).avi
- 第一行选择目录中最后修改的 avi 文件(不递归),并提取其名称中的数字。
- 第二行在原先的名称上加1并生成文件。
答案4
@jherran 提供的解决方案应该可以满足您的需求。如果您只是希望脚本给您下一个文件名,而不是为您创建它,将脚本末尾的“touch”更改为“echo”。
但是,随着您添加许多文件,这会变得越来越慢。如果您需要连续的数字,您可以将当前数字写入文件,然后在写入下一个文件之前将其读回,写出新数字,然后写出文件。我在下面提供了执行此操作的示例代码。
但是,如果您不需要连续的数字,而只是想要不冲突的文件名,那么日期戳就非常有用。它们按您期望的方式排序,如果您不进行时间旅行,它们会单调递增。
对于您提出的这个问题 (shell 脚本返回下一个值) 的答案,基于我上面关于仅使用计数器文件的建议,如下所示:
#!/usr/bin/sh
if [ -f counter.txt ]; then
{
VAL=`cat counter.txt`
echo "out-$VAL.avi"
VAL=`expr $VAL + 1`
echo "$VAL" > counter.txt
exit 0
}
fi
echo "out-1.avi"
echo "2" > counter.txt
exit 0
或者,如果您想采用我的建议,使用日期戳来实现唯一性和排序,只需让您的文件写入程序抓取此命令的输出:
date +%F-%T
或者任何你认为有用的日期和时间粒度。上面的代码会给你类似这样的结果:
2014-12-01-16:41:33
在末尾加上“.avi”您就拥有了带时间戳的文件名,精确到秒。