重命名文件名中包含多个变量的文件

时间:2015-06-19 11:05:40

标签: bash for-loop rename mv

我有多种格式的文件:onActivityResultthis-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是3个数字的任意组合。所有文件都在一个目录中。

我尝试使用123mv,但我没有成功

我在这里搜索并查看了所有文件重命名问题,但没有一个符合我的情况

2 个答案:

答案 0 :(得分:1)

解释#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
  1. 我们遍历所有*.txt个文件。
    1. 我们会检查它是否未定位_r_*.txt,也不会重命名为_i_*.txt文件。
    2. 如果是,我们会忽略它。如果不是,我们:
      1. Extract the base file name,无延伸,$y
      2. 依赖* glob star运算符输出源文件名和建议的目标文件名。如果匹配多个文件,它将打印所有文件。如果没有,则只打印源文件名。根据这些情况,您可以移动文件或保留文件。
  2. 要将_r_替换为变量_i_中的$z,您可能需要使用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"'\1/')"
        echo "$x" "$y"
    done
    
    1. 首先我们声明变量i并将其设置为0.
    2. 然后我们遍历所有*.txt个文件。
      1. 然后,我们使用$ilet i+=1增加1。
      2. 然后我们使用sed获取新文件名,其中:
        1. 我们用s/A/B/替换(.[a-z]*$)文件扩展名_r_
        2. 后跟$i
        3. 后跟\1运算符左侧括号\(\)捕获的文件扩展名s///
        4. 我们使用'"变量包装普通文本。请注意表达式中引用如何更改两次。
      3. 然后我们回显原始文件名和新文件名,而不是移动,以便我们可以验证结果是否正确。
    3. 看到它在行动:

      rr-@herp:~$ i=0; for x in *.txt; do let i+=1; y="$(echo "$x"|sed 's/\(\.[a-z]*\)$/_r_'"$i"'\1/')"; echo "$x" "$y"; done
      mm todo.txt mm todo_r_1.txt
      mm.txt mm_r_2.txt
      

      注释

      1. 如果您需要验证$i文件是否已存在,可以使用if [ -f $target ]
      2. 您可以使用find查找文件,但它更复杂,您应该在网上搜索如何将findfor循环一起使用。

答案 1 :(得分:0)

我将技术改为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中执行此操作,则应使用sedawk轻松移植。