重命名文件名中包含多个变量的文件
Renaming files with multiple variables in the file names
我有多个这种格式的文件:this-is-text_r_123.txt
和 this-is-text.txt
。
我想做的(最好使用 for
循环)是将所有 this-is-text.txt
文件重命名为它们相应的 this-is-text_r_123.txt
匹配项,但有一个 i
文件名中的 r
。考虑到 this-is-text
是一个随机文本(一个文件与另一个文件不同),而上例中的 123
是 3 个数字的任意组合。所有文件都在一个目录中。
我尝试了 mv
和 rename
,但没有成功
我在这里搜索并查看了所有文件重命名问题,但 none 符合我的情况
解读 #1
如果您想将 *.txt
重命名为它们的 _r_<NUMBER>.txt
副本,并且您确定每个 .txt
文件只存在一个这样的文件,您可以使用以下方法:
for x in *.txt
do
if [[ "$x" != *_r_* && "$x" != *_i_* ]]; then
y="${x%.*}"
echo "$x" "${y}_r_"*
fi
done
- 我们遍历所有
*.txt
个文件。
- 我们检查它是否不是目标
_r_*.txt
也不是要重命名为 _i_*.txt
文件。
- 如果是,我们忽略它。如果不是,我们:
- Extract the base file name,没有扩展名,到
$y
。
- 输出源文件名和建议的目标文件名,依赖于
*
glob 星号运算符。如果匹配多个文件,它将打印所有文件。如果有none,则只打印源文件名。根据这些情况,您可以移动文件或保留文件。
要将变量 $z
中的 _r_
替换为 _i_
,您可能需要使用 z=${z/_r_/_i_}
。这将在第 1.2.2 点中证明是有用的。
解读 #2
要移动每个 *.txt
文件并为其分配一个编号:
i=0
for x in *.txt
do
let i+=1
y="$(echo "$x"|sed 's/\(\.[a-z]*\)$/_r_'"$i"'/')"
echo "$x" "$y"
done
- 首先我们声明变量
i
并将其设置为0。
- 然后我们遍历所有
*.txt
个文件。
- 然后我们使用
let i+=1
将$i
加1。
- 然后我们使用
sed
得到新的文件名,其中:
- 我们将文件扩展名 (
.[a-z]*$
) 替换 (s/A/B/
) 为 _r_
,
- 接着是
$i
、
- 后跟
s///
运算符左侧的括号 \(\)
捕获的文件扩展名 (</code>)。</li>
<li>我们用 <code>'
包装普通文本,用 "
包装变量。请注意表达式中的引号是如何更改两次的。
- 然后我们回显原始文件名和新文件名而不是移动,以便我们可以验证结果是否正确。
实际操作:
rr-@herp:~$ i=0; for x in *.txt; do let i+=1; y="$(echo "$x"|sed 's/\(\.[a-z]*\)$/_r_'"$i"'/')"; echo "$x" "$y"; done
mm todo.txt mm todo_r_1.txt
mm.txt mm_r_2.txt
注释
- 如果你需要验证第
$i
个文件是否已经存在,你可以使用if [ -f $target ]
.
- 您可以使用
find
来查找文件,但它更复杂,您应该在网上搜索如何使用 find
和 for
循环。
我将技术更改为 Python 以演示如何使用比 bash 更方便的语言来执行此操作:
#!/usr/bin/python3
import glob
import re
text_files = glob.glob('*.txt')
#divide the files into two groups: "normal" files without _r and "target" files with _r
normal_files = {}
target_files = {}
for path in text_files:
#extract "key" (meaning part of file name without _r or _i)
#as well as whether the file contains _r or _i, or not
#using regular expressions:
result = re.match('(?P<key>.*?)(?P<target>_[ri]_?\d*)?\..*$', path)
if result:
if result.group('target'):
target_files[result.group('key')] = path
else:
normal_files[result.group('key')] = path
print(normal_files)
print(target_files)
#now figure out how to rename the files using the built dictionaries:
for key, path in normal_files.items():
if key in target_files:
target_path = target_files[key].replace('_r', '_i')
print('Renaming %s to %s' % (path, target_path))
对于以下一组文件:
asd.txt
asd_r_1.txt
test test.txt
test test_r2.txt
another test_i_1.txt
此脚本将生成:
{'test test': 'test test.txt', 'asd': 'asd.txt'}
{'test test': 'test test_r2.txt', 'another test': 'another test_i_1.txt', 'asd': 'asd_r_1.txt'}
Renaming test test.txt to test test_i2.txt
Renaming asd.txt to asd_i_1.txt
你应该可以用这个移动文件。
如您所见,有效。
如果您真的需要在bash中执行此操作,使用sed
或awk
应该很容易移植。
我有多个这种格式的文件:this-is-text_r_123.txt
和 this-is-text.txt
。
我想做的(最好使用 for
循环)是将所有 this-is-text.txt
文件重命名为它们相应的 this-is-text_r_123.txt
匹配项,但有一个 i
文件名中的 r
。考虑到 this-is-text
是一个随机文本(一个文件与另一个文件不同),而上例中的 123
是 3 个数字的任意组合。所有文件都在一个目录中。
我尝试了 mv
和 rename
,但没有成功
我在这里搜索并查看了所有文件重命名问题,但 none 符合我的情况
解读 #1
如果您想将 *.txt
重命名为它们的 _r_<NUMBER>.txt
副本,并且您确定每个 .txt
文件只存在一个这样的文件,您可以使用以下方法:
for x in *.txt
do
if [[ "$x" != *_r_* && "$x" != *_i_* ]]; then
y="${x%.*}"
echo "$x" "${y}_r_"*
fi
done
- 我们遍历所有
*.txt
个文件。- 我们检查它是否不是目标
_r_*.txt
也不是要重命名为_i_*.txt
文件。 - 如果是,我们忽略它。如果不是,我们:
- Extract the base file name,没有扩展名,到
$y
。 - 输出源文件名和建议的目标文件名,依赖于
*
glob 星号运算符。如果匹配多个文件,它将打印所有文件。如果有none,则只打印源文件名。根据这些情况,您可以移动文件或保留文件。
- Extract the base file name,没有扩展名,到
- 我们检查它是否不是目标
要将变量 $z
中的 _r_
替换为 _i_
,您可能需要使用 z=${z/_r_/_i_}
。这将在第 1.2.2 点中证明是有用的。
解读 #2
要移动每个 *.txt
文件并为其分配一个编号:
i=0
for x in *.txt
do
let i+=1
y="$(echo "$x"|sed 's/\(\.[a-z]*\)$/_r_'"$i"'/')"
echo "$x" "$y"
done
- 首先我们声明变量
i
并将其设置为0。 - 然后我们遍历所有
*.txt
个文件。- 然后我们使用
let i+=1
将$i
加1。 - 然后我们使用
sed
得到新的文件名,其中:- 我们将文件扩展名 (
.[a-z]*$
) 替换 (s/A/B/
) 为_r_
, - 接着是
$i
、 - 后跟
s///
运算符左侧的括号\(\)
捕获的文件扩展名 (</code>)。</li> <li>我们用 <code>'
包装普通文本,用"
包装变量。请注意表达式中的引号是如何更改两次的。
- 我们将文件扩展名 (
- 然后我们回显原始文件名和新文件名而不是移动,以便我们可以验证结果是否正确。
- 然后我们使用
实际操作:
rr-@herp:~$ i=0; for x in *.txt; do let i+=1; y="$(echo "$x"|sed 's/\(\.[a-z]*\)$/_r_'"$i"'/')"; echo "$x" "$y"; done
mm todo.txt mm todo_r_1.txt
mm.txt mm_r_2.txt
注释
- 如果你需要验证第
$i
个文件是否已经存在,你可以使用if [ -f $target ]
. - 您可以使用
find
来查找文件,但它更复杂,您应该在网上搜索如何使用find
和for
循环。
我将技术更改为 Python 以演示如何使用比 bash 更方便的语言来执行此操作:
#!/usr/bin/python3
import glob
import re
text_files = glob.glob('*.txt')
#divide the files into two groups: "normal" files without _r and "target" files with _r
normal_files = {}
target_files = {}
for path in text_files:
#extract "key" (meaning part of file name without _r or _i)
#as well as whether the file contains _r or _i, or not
#using regular expressions:
result = re.match('(?P<key>.*?)(?P<target>_[ri]_?\d*)?\..*$', path)
if result:
if result.group('target'):
target_files[result.group('key')] = path
else:
normal_files[result.group('key')] = path
print(normal_files)
print(target_files)
#now figure out how to rename the files using the built dictionaries:
for key, path in normal_files.items():
if key in target_files:
target_path = target_files[key].replace('_r', '_i')
print('Renaming %s to %s' % (path, target_path))
对于以下一组文件:
asd.txt
asd_r_1.txt
test test.txt
test test_r2.txt
another test_i_1.txt
此脚本将生成:
{'test test': 'test test.txt', 'asd': 'asd.txt'}
{'test test': 'test test_r2.txt', 'another test': 'another test_i_1.txt', 'asd': 'asd_r_1.txt'}
Renaming test test.txt to test test_i2.txt
Renaming asd.txt to asd_i_1.txt
你应该可以用这个移动文件。
如您所见,有效。
如果您真的需要在bash中执行此操作,使用sed
或awk
应该很容易移植。