Переименуйте несколько файлов, имена которых включают "*"
У меня есть набор файлов, имена которых содержат символ *
, Например, имя файла может быть ***abcdef
, Я хочу изменить это имя файла на 3_abcdef
, заменяя *
с количеством *
это было там.
У меня есть скрипт для переименования нескольких файлов, но я не знаю, как изменить этот скрипт для выполнения вышеуказанной задачи.
Это то, что я имею до сих пор:
find drp/ -depth -name "*abc.tab" -exec rename 's/\abc.tab$/xyz.tab/' {} +
Как я могу адаптировать его к этой задаче?
3 ответа
Вы можете использовать фактическое выражение с переименованием. В этом случае мы сопоставляем столько звездочек, сколько есть, а затем заменяем их на длину совпадения:
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
Incase, если вам нужен скрипт с одним вкладышем.
$ 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
Я бы порекомендовал использовать скрипт оболочки, так как он имеет больше проверок.
Предполагая, что вы хотите заменить число предшествующих "*" на фактическое число (как в вашем примере), и принимая во внимание возможность существования подпапок и игнорирования невидимых файлов, опция 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