gpt4 book ai didi

linux - 基于多种模式重命名文件的更好方法

转载 作者:IT王子 更新时间:2023-10-29 00:05:13 25 4
gpt4 key购买 nike

我下载的很多文件的文件名中都有废话/垃圾邮件,例如

[ www.crap.com ] file.name.ext

www.crap.com - file.name.ext

我想出了两种处理它们的方法,但它们看起来都很笨拙:

带参数扩展:

if [[ ${base_name} != ${base_name//\[+([^\]])\]} ]]
then
mv -v "${dir_name}/${base_name}" "${dir_name}/${base_name//\[+([^\]])\]}" &&
base_name="${base_name//\[+([^\]])\]}"
fi

if [[ ${base_name} != ${base_name//www.*.com - /} ]]
then
mv -v "${dir_name}/${base_name}" "${dir_name}/${base_name//www.*.com - /}" &&
base_name="${base_name//www.*.com - /}"
fi

# more of these type of statements; one for each type of frequently-encountered pattern

然后用 echo/sed:

tmp=`echo "${base_name}" | sed -e 's/\[[^][]*\]//g' | sed -e 's/\s-\s//g'`
mv "${base_name}" "{tmp}"

我觉得参数扩展是两者中最糟糕的,但我喜欢它,因为我能够保留分配给文件的相同变量,以便在重命名后进行进一步处理(上面的代码用于名为文件下载完成后的每个文件)。

所以无论如何,我希望有一种更好/更干净的方法来完成上述操作,比我更有知识的人可以向我展示,最好是以一种允许我轻松地将旧/原始变量重新分配给新/重命名文件的方式.

谢谢

最佳答案

两个答案:使用重命名或使用

因为有些人不喜欢 perl,所以我写了我的 bash only version

使用rename 命令重命名文件。

简介

是的,这是 rename 命令的典型工作,它专门设计用于:

man rename | sed -ne '/example/,/^[^ ]/p'
For example, to rename all files matching "*.bak" to strip the
extension, you might say

rename 's/\.bak$//' *.bak

To translate uppercase names to lower, you'd use

rename 'y/A-Z/a-z/' *

更多定向样本

只需删除所有空格方括号:

rename 's/[ \[\]]*//g;' *.ext

重命名所有.jpg,从1开始编号:

rename 's/^.*$/sprintf "IMG_%05d.JPG",++$./e' *.jpg

演示:

touch {a..e}.jpg
ls -ltr
total 0
-rw-r--r-- 1 user user 0 sep 6 16:35 e.jpg
-rw-r--r-- 1 user user 0 sep 6 16:35 d.jpg
-rw-r--r-- 1 user user 0 sep 6 16:35 c.jpg
-rw-r--r-- 1 user user 0 sep 6 16:35 b.jpg
-rw-r--r-- 1 user user 0 sep 6 16:35 a.jpg
rename 's/^.*$/sprintf "IMG_%05d.JPG",++$./e' *.jpg
ls -ltr
total 0
-rw-r--r-- 1 user user 0 sep 6 16:35 IMG_00005.JPG
-rw-r--r-- 1 user user 0 sep 6 16:35 IMG_00004.JPG
-rw-r--r-- 1 user user 0 sep 6 16:35 IMG_00003.JPG
-rw-r--r-- 1 user user 0 sep 6 16:35 IMG_00002.JPG
-rw-r--r-- 1 user user 0 sep 6 16:35 IMG_00001.JPG

以安全的方式匹配 SO 问题的完整语法

使用 rename 实用程序有一种强大而安全的方法:

因为这是 常用工具,我们得用perl语法:

rename 'my $o=$_;
s/[ \[\]]+/-/g;
s/-+/-/g;
s/^-//g;
s/-\(\..*\|\)$/$1/g;
s/(.*[^\d])(|-(\d+))(\.[a-z0-9]{2,6})$/
my $i=$3;
$i=0 unless $i;
sprintf("%s-%d%s", $1, $i+1, $4)
/eg while
$o ne $_ &&
-f $_;
' *

测试规则:

touch '[ www.crap.com ] file.name.ext' 'www.crap.com - file.name.ext'
ls -1
[ www.crap.com ] file.name.ext
www.crap.com - file.name.ext
rename 'my $o=$_; ...
...
...' *
ls -1
www.crap.com-file.name-1.ext
www.crap.com-file.name.ext

touch '[ www.crap.com ] file.name.ext' 'www.crap.com - file.name.ext'
ls -1
www.crap.com-file.name-1.ext
[ www.crap.com ] file.name.ext
www.crap.com - file.name.ext
www.crap.com-file.name.ext
rename 'my $o=$_; ...
...
...' *
ls -1
www.crap.com-file.name-1.ext
www.crap.com-file.name-2.ext
www.crap.com-file.name-3.ext
www.crap.com-file.name.ext

...等等...

...当您不使用-f 标志来重命名 命令时它是安全的:文件不会被覆盖,如果出了点问题。

使用 重命名文件和所谓的bashisms:

我更喜欢使用专用实用程序来完成此操作,但这甚至可以使用 pure 来完成(又名没有任何 fork )

没有使用除 bash 之外的任何其他二进制文件(没有 sedawktr 或其他):

#!/bin/bash

for file;do
newname=${file//[ \]\[]/.}
while [ "$newname" != "${newname#.}" ] ;do
newname=${newname#.}
done
while [ "$newname" != "${newname//[.-][.-]/.}" ] ;do
newname=${newname//[.-][.-]/-};done
if [ "$file" != "$newname" ] ;then
if [ -f $newname ] ;then
ext=${newname##*.}
basename=${newname%.$ext}
partname=${basename%%-[0-9]}
count=${basename#${partname}-}
[ "$partname" = "$count" ] && count=0
while printf -v newname "%s-%d.%s" $partname $[++count] $ext &&
[ -f "$newname" ] ;do
:;done
fi
mv "$file" $newname
fi
done

以文件作为参数运行,例如:

/path/to/my/script.sh \[*
  • 用点替换空格和方括号
  • 仅用一个 替换 .--.--.. 序列>-
  • 测试文件名是否不同,没有什么可做的。
  • 测试文件是否存在newname...
  • 拆分文件名、计数器和扩展名,用于制作索引新名称
  • 如果文件存在新名称则循环
  • 最后重命名文件。

关于linux - 基于多种模式重命名文件的更好方法,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/20629302/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com