我有一个像这样的文件编号列表:
01_file_name.log
01_file_name.txt
02_file_name.log
02_file_name.txt
03_file_name.log
03_file_name.txt
04_file_name.log
04_file_name.txt
05_file_name.log
05_file_name.txt
我想为所有03*
和04*
文件插入新文件。因此,从病房的编号开始03
,所有文件都需要移动/重命名,其前导编号增加 2,因此列表将如下所示:
01_file_name.log
01_file_name.txt
02_file_name.log
02_file_name.txt
05_file_name.log
05_file_name.txt
06_file_name.log
06_file_name.txt
07_file_name.log
07_file_name.txt
我正在考虑这样的事情:
bash script.sh 03 02
while 03
on$1
是要开始的文件名的编号和要添加的编号02
。$2
我尝试通过嵌套来实现此目的for-loop
,但我不得不放弃使用计数器的组合((++))
,以使循环仅运行病房中给定编号的文件。
答案1
这就是你想要的。一件事:我认为它只适用于 BASH。
MAXDIGITS
是可选的,我把它放在那里,以防您需要使用三位数或更多。如果不使用,请删除相应行。
#!/bin/bash
BOTTOM=$1
SHIFT=$2
MAXDIGITS=0$3
for filename in $(ls -r *.{txt,log}); do
PREFIX=${filename%%_*}
NEWPREFIX=$(expr $PREFIX + $SHIFT)
if [ $PREFIX -ge $BOTTOM ]; then
NEWPREFIX=$(printf %${MAXDIGITS}d $NEWPREFIX)
mv $filename ${NEWPREFIX}_${filename#*_}
fi
done
使用方法:
./myscript <BOTTOM> <SHIFT> <MAXDIGITS>
### Example:
./miscript 03 02 2 #This means "Start at 03_filename.*, shift the prefixes by 2 and use 2 digits to construct the new prefixes".
如果同一目录中有其他不符合相同语法(prefix_filename.{txt,log})的文件,则必须过滤它们。另外,我使用“_”来分隔前缀和文件名,因此如果您更改它,则需要修复代码。
答案2
就其价值而言,这是一个bash
涉及两个的单行流程替代和一个非常简单的awk
过程:
$ ls -r -1 *_file_name.{txt,log} # list initial files in reverse order
05_file_name.log
05_file_name.txt
04_file_name.log
03_file_name.txt
03_file_name.log
03_file_name.txt
02_file_name.log
02_file_name.txt
01_file_name.log
01_file_name.txt
$ source <(awk 'BEGIN{FS="_"} $1>2 {prefix=$1+2; printf ("mv -f %s %0.2d_%s_%s\n",$0,prefix,$2,$3)}' <(ls -r -1 *_file_name.{log,txt}))
$ ls -1 *_file_name.{txt,log} # list resulting files
01_file_name.log
01_file_name.txt
02_file_name.log
02_file_name.txt
05_file_name.log
05_file_name.txt
06_file_name.log
06_file_name.txt
07_file_name.log
07_file_name.txt
解释:
上面一行是从右到左阅读的,或者至少是“理解”的。
ls -r -1 *_file_name.{log,txt}
以一列格式按相反顺序列出要处理的所有文件。
请注意,如果文件前缀(用 符号表示*
)包含非数字字符,您可能会得到不可预见/不需要的结果。为了防止这种情况,请过滤此阶段要处理的文件。<(...)
工艺替代。它允许使用文件描述符(即称为命名管道的特殊临时文件)引用先前的结果输出。有关详细信息,请man bash
在终端中发布。awk
脚本:BEGIN{FS="_"}
在开始处理记录之前,将记录的字段分隔符设置为“_”(awk 的第一个块)awk
的第二个块的条件,$1>2
:仅处理文件名前缀严格大于2的记录prefix=$1+2
定义 awk 的“前缀”内部变量。使其在数值上等于 prefix$1
+ 2- 用于
printf("my_format",var1,var2,...)
打印格式化的命令,以换行符分隔。请注意,格式化涉及%0.2d
,即将 的变量“前缀”打印awk
为两位数,必要时用 0 填充。输出是:
mv -f 05_file_name.log 07_file_name.log
mv -f 05_file_name.txt 07_file_name.txt
mv -f 04_file_name.log 06_file_name.log
mv -f 04_file_name.txt 06_file_name.txt
mv -f 03_file_name.log 05_file_name.log
mv -f 03_file_name.txt 05_file_name.txt
- 将排序后的输出视为另一个文件(第二个进程替换)并获取它来执行命令
mv -f ...
。
如果您想知道为什么重复使用入站或出站流程替换(不是 POSIX 的东西!) inbash
是有利的,请参阅这例如。
最后说明:
在上面的一行代码中包含运行时参数并将其封装在可执行 shell 脚本中很容易,从定义VAR1
并VAR2
分配给 的awk
过程开始:
$ source <(awk -v VAR1=2 -v VAR2=2 'BEGIN{FS="_"} $1>VAR1 {prefix=$1+VAR2; printf ("mv -f %s %0.2d_%s_%s\n",$0,prefix,$2,$3)}' <(ls -r -1 *_file_name.{log,txt}))
在可执行脚本中script.sh
:
$ cat script.sh
#!/usr/bin/bash
if [ "$#" -eq 2 ] ; then
source <(awk -v VAR1=$1 -v VAR2=$2 'BEGIN{FS="_"} $1>VAR1 {prefix=$1+VAR2; printf ("mv -f %s %0.2d_%s_%s\n",$0,prefix,$2,$3)}'
<(ls -r -1 *_file_name.{log,txt})
)
exit 0
else
echo " Usage: script.sh VAR1 VAR2.\n Abort execution (exit code 1)."
exit 1
fi
其中VAR1
和VAR2
具有 OP 中定义的含义。如果您需要在生产环境中使用该脚本,我强烈建议添加许多检查和故障保护,以确保您的输入文件和变量的值始终是预期的。
@MarceloCastro 的脚本很好,尽管它基于for
循环,我倾向于尽可能避免这种循环。 for
循环往往很慢,如果您处理一个循环,您可能会注意到这一点大的文件数量。
答案3
我制作了这个适合您目标的脚本。
for files in *.extensions
do
num=$(echo "$files" | awk '{print $1}' | cut -c1-2)
if [ $num -gt 2 ]; then
AS=$((num+2))
temp=$(echo "$files" | cut -c 3-)
mv $files 0$AS"$temp"
fi
done
答案4
和zsh
:
$ autoload zmv
$ zmv -n -f '(<3->)(_*)(#qnOn)' '${(l:2::0:)$(($1+2))}$2'
mv -- 05_file_name.txt 07_file_name.txt
mv -- 05_file_name.log 07_file_name.log
mv -- 04_file_name.txt 06_file_name.txt
mv -- 04_file_name.log 06_file_name.log
mv -- 03_file_name.txt 05_file_name.txt
mv -- 03_file_name.log 05_file_name.log
然后删除-n
(用于空运行)以实际执行此操作。
zmv pattern replacement
:zmv
是一个可自动加载的函数,它利用强大的 zsh glob 和扩展运算符来执行复杂的文件重命名。<x-y>
将十进制数 x 与 y 匹配。(#q...)
全局限定符nOn
: ame 的n
数字o
rder(与大写 O 反转)n
。因此,由于我们正在增加数字,因此05...
将根据需要在此之前出现。04...
${(l:n::padding:)expansion}
:l
将扩展填充到长度n使用填充。因此${(l:2::0:)}
,使用 时,将 0 保留到长度 2。$(($1+2))
,第一个捕获的组增加 2。$2
:第二个捕获组:前导数字之后的内容。