Переименуйте несколько файлов, имена которых включают '*'

У меня есть ряд файлов, имена которых содержат символ *. Например, имя файла могло быть ***abcdef. Я хочу изменить это имя файла на 3_abcdef, замена * с количеством * это было там.

У меня есть сценарий для переименования нескольких файлов, но я не знаю, как изменить тот сценарий, чтобы сделать вышеупомянутую задачу.

Это - wjat, который я имею до сих пор:

find drp/ -depth -name "*abc.tab" -exec rename 's/\abc.tab$/xyz.tab/' {} +

Как я могу адаптировать его к этой задаче?

2
задан 31 October 2014 в 17:25

3 ответа

Принятие, как которое требуется заменить количество предшествования "*" фактическим числом (в примере), и принятие во внимание возможности существования sub папок и игнорирования невидимых файлов, опция Python, будет:

#!/usr/bin/env python3

import os
import shutil
import sys

sourcedir = sys.argv[1]

for root, dirs, files in os.walk(sourcedir):
    for name in files:
        if not name.startswith(".") and name.count("*") != 0:
            number = name.count("*"); newname = str(number)+"_"+name.replace("*", "")
            shutil.move(root+"/"+name, root+"/"+newname)

Скопируйте его в пустой файл, сохраните его как rename.py, выполните его командой:

python3 path/to/rename.py </path/to/files>

это переименовывает

****banana.txt
**monkey.mp3
**************test

в:

4_banana.txt
2_monkey.mp3
14_test
1
ответ дан 6 October 2019 в 21:47

Можно использовать фактическое выражение с, переименовывают. В этом случае мы соответствуем стольким же звездочек, сколько существует и затем заменяет это продолжительностью соответствия:

rename 's/^[*]+/sprintf("%d_", length $&)/e' -vn *

Если это выглядит правильным, удалите -n аргумент. Это должно просто там позволить Вам тестировать его безопасно.

Вот моя тестовая обвязка:

$ touch \*{,\*{,\*}}abc.tab
$ rename 's/^[*]+/sprintf("%d_", length $&)/e' -vn *
***abc.tab renamed as 3_abc.tab
**abc.tab renamed as 2_abc.tab
*abc.tab renamed as 1_abc.tab

Если Вы также хотите сделать, другой переименовывает, можно объединить его в цепочку в:

$ rename 's/^[*]+/sprintf("%d_", length $&)/e; s/abc/xyz/' -vn *
***abc.tab renamed as 3_xyz.tab
**abc.tab renamed as 2_xyz.tab
*abc.tab renamed as 1_xyz.tab
7
ответ дан 2 December 2019 в 01:30

Упакуйте при необходимости в одном сценарии удара лайнера.

$ find . -type f -exec bash -c 'file=$(basename "$0"); rn=$(echo "$file"|grep -o "*"|wc -l); on=$(echo "$file"|tr -d "*"); mv "$file" "${rn}_${on}"' {} \;

$ ls 
0_a.txt  1_a.txt  2_a.txt  3_a.txt

И если Вам нужен сценарий оболочки.

#!/bin/bash

changed=0

for file in *
do
    rn=$(echo "$file"|grep -o '*'| wc -l)
    on=$(echo "$file"|tr -d '*')
    if [ "$rn" -ne 0 ]
    then
        mv -v "$file" "$rn"_"$on"
        ((changed++))
    fi
done

if [ $changed -gt 0 ]
then
    echo "Have renamed $changed files"
else
    echo "There are no files to rename"
fi

Вывод

$ ./a.sh 
`***a.txt' -> `3_a.txt'
`**a.txt' -> `2_a.txt'
`******b.txt' -> `6_b.txt'
`**b.txt' -> `2_b.txt'
Have renamed 4 files

Я рекомендовал бы использовать сценарий оболочки, поскольку он имеет больше проверок.

1
ответ дан 2 December 2019 в 01:30

Другие вопросы по тегам:

Похожие вопросы: