tom*_*myk 82 command-line bash rename batch-rename
我有很多带有.abc
扩展名的文件,想将它们更改为.edefg
如何从命令行执行此操作?
我有一个包含许多子文件夹的根文件夹,因此该解决方案应该递归地工作。
gei*_*rha 105
一种可移植的方式(适用于任何 POSIX 兼容系统):
find /the/path -depth -name "*.abc" -exec sh -c 'mv "$1" "${1%.abc}.edefg"' _ {} \;
Run Code Online (Sandbox Code Playgroud)
在 bash4 中,您可以使用 globstar 来获取递归 globs (**):
shopt -s globstar
for file in /the/path/**/*.abc; do
mv "$file" "${file%.abc}.edefg"
done
Run Code Online (Sandbox Code Playgroud)
rename
Ubuntu 中的 (perl)命令可以使用 perl 正则表达式语法重命名文件,您可以将其与 globstar 或find
:
# Using globstar
shopt -s globstar
files=(/the/path/**/*.abc)
# Best to process the files in chunks to avoid exceeding the maximum argument
# length. 100 at a time is probably good enough.
# See http://mywiki.wooledge.org/BashFAQ/095
for ((i = 0; i < ${#files[@]}; i += 100)); do
rename 's/\.abc$/.edefg/' "${files[@]:i:100}"
done
# Using find:
find /the/path -depth -name "*.abc" -exec rename 's/\.abc$/.edefg/' {} +
Run Code Online (Sandbox Code Playgroud)
另见http://mywiki.wooledge.org/BashFAQ/030
Cha*_*kra 53
如果所有文件都在同一文件夹中,这将执行所需的任务
rename 's/.abc$/.edefg/' *.abc
Run Code Online (Sandbox Code Playgroud)
要递归地重命名文件,请使用以下命令:
find /path/to/root/folder -type f -name '*.abc' -print0 | xargs -0 rename 's/.abc$/.edefg/'
Run Code Online (Sandbox Code Playgroud)
Chr*_*ong 14
递归重命名的一个问题是,无论您使用什么方法来定位文件,它都会将整个路径传递给rename
,而不仅仅是文件名。这使得很难在嵌套文件夹中进行复杂的重命名。
我用find
的-execdir
动作来解决这个问题。如果使用-execdir
代替-exec
,则从包含匹配文件的子目录运行指定的命令。因此,它不会将整个路径传递给rename
,而是只传递./filename
。这使得编写正则表达式变得更加容易。
find /the/path -type f \
-name '*.abc' \
-execdir rename 's/\.\/(.+)\.abc$/version1_$1.abc/' '{}' \;
Run Code Online (Sandbox Code Playgroud)
详细:
-type f
表示只查找文件,不查找目录-name '*.abc'
表示只匹配以 .abc 结尾的文件名'{}'
是标记-execdir
将插入找到的路径的位置的占位符。单引号是必需的,以允许它处理带有空格和 shell 字符的文件名。-type
和之后的反斜杠-name
是 bash 行继续符。我使用它们使这个示例更具可读性,但如果您将命令全部放在一行中,则不需要它们。-execdir
行尾的反斜杠是必需的。它用于转义分号,分号终止由-execdir
. 乐趣!正则表达式的解释:
s/
正则表达式的开始\.\/
匹配 -execdir 传入的前导 ./。使用 \ 转义 . 和 / 元字符(注意:这部分因您的 版本而异find
。请参阅用户@apollo 的评论)(.+)
匹配文件名。括号捕获匹配供以后使用\.abc
转义点,匹配 abc$
将匹配锚定在字符串的末尾
/
标记正则表达式“匹配”部分的结束,以及“替换”部分的开始
version1_
将此文本添加到每个文件名
$1
引用现有的文件名,因为我们用括号捕获了它。如果您在“匹配”部分使用多组括号,您可以在此处使用 $2、$3 等引用它们。.abc
新文件名将以 .abc 结尾。无需在“替换”部分对此处的点元字符进行转义/
正则表达式结束前
find /the/path -type f \
-name '*.abc' \
-execdir rename 's/\.\/(.+)\.abc$/version1_$1.abc/' '{}' \;
Run Code Online (Sandbox Code Playgroud)
后
tree --charset=ascii
|-- a_file.abc
|-- Another.abc
|-- Not_this.def
`-- dir1
`-- nested_file.abc
Run Code Online (Sandbox Code Playgroud)
提示:rename
's -n 选项很有用。它会进行一次试运行并向您显示它将更改的名称,但不会进行任何更改。
另一种便携方式:
find /the/path -depth -type f -name "*.abc" -exec sh -c 'mv -- "$1" "$(dirname "$1")/$(basename "$1" .abc).edefg"' _ '{}' \;
Run Code Online (Sandbox Code Playgroud)
小智 5
# Rename all *.txt to *.text
for f in *.txt; do
mv -- "$f" "${f%.txt}.text"
done
Run Code Online (Sandbox Code Playgroud)
另请参阅有关为什么不应解析的条目ls
。
编辑:如果您必须使用基本名称,您的语法将是:
for f in *.txt; do
mv -- "$f" "$(basename "$f" .txt).text"
done
Run Code Online (Sandbox Code Playgroud)
https://unix.stackexchange.com/questions/19654/changing-extension-to-multiple-files