Пакетное переименование, добавьте лишние "." символ в позиции 3 в имени файла, рекурсивно

Я изо всех сил пытался сделать эту работу, но я не очень хорошо с регулярным выражением. Это то, что я пытался сделать, и это не сработало (через 50 минут все еще продолжалось без видимых изменений):

while IFS= read -r -d '' file; do mv $file ${file:0:2}.${file:2}; done

Заранее спасибо!

3 ответа

Решение

Одна проблема, с которой вам придется столкнуться при рекурсивном переименовании файлов в каталогах, - это отделение имени файла (которое вы хотите изменить) от пути. Вы не можете просто удалить компонент пути, потому что тогда ваши файлы будут перемещены, а не просто переименованы.

Чтобы использовать ваш оригинальный метод, я думаю, вам нужно сделать что-то вроде

while read -r -d '' f; do 
  file="${f##*/}"; path="${f%/*}" 
  echo mv -- "$path/$file" "$path/${file:0:2}"."${file:2}"
done < <(find -type f -iname "*.wav" -print0)

Другой вариант заключается в использовании find командования -execdir вместо -exec, Я думаю, можно с уверенностью предположить, что результаты будут представлены вашей команде переименования (используете ли вы rename или же mv) только с ведущим ./ как путь, и в этом случае вы можете сделать

find -type f -iname "*.wav" -execdir rename -nv -- 's|\./..|$&.|' {} +

или используя более перламутровый вариант

find -type f -iname "*.wav" -execdir rename -nv -- 's|\./..\K|.|' {} +

или используя что-то более эквивалентное вашему оригиналу mv подход

find -type f -iname "*.wav" -execdir bash -c 'echo mv -- "$0" "${0:0:4}"."${0:4}"' {} \;

(обратите внимание, что индексы подстроки были увеличены на 2, чтобы учесть ведущие ./ компонент пути).

Если ваша версия find не имеет -execdir вариант, вы можете изменить rename регулярное выражение, чтобы пропустить самый длинный совпадающий префикс пути, например

find -type f -iname "*.wav" -exec rename -nv -- 's|.*/..\K|.|' {} +

Примечание: во всех этих выражениях есть переключатели no-op (либо переименуйте -n вариант или echo команда), чтобы вы могли проверить, что они будут делать до совершения.

Это работает (проверено):

#!/bin/bash

filenames=$(find . -type f) # stores all filenames in $filenames
for filename in $filenames; do # for each member in $filenames
    newfilename=$(echo "$filename" | sed 's/\(.*\)\/\(..\)\(.*\)$/\1\/\2\.\3/') # edits $filename by adding a . after the second character and stores the edited string in $newfilename
    mv "$filename" "$newfilename" # renames $filename to $newfilename
done

Это можно легко сделать, используя rename:

rename 's/ /\./' file.txt

Пример:

$ ls -l
-rw-rw-r-- 1 user user 0 Mar 30 04:22 01 Song Title.flac
$ rename 's/ /\./' 01\ Song\ Title.flac 
$ ls -l
-rw-rw-r-- 1 user user 0 Mar 30 04:22 01.Song Title.flac

РЕДАКТИРОВАТЬ: Если вы хотите пробел после 01.:

rename 's/ /\. /' file.txt

Если вы хотите, чтобы все файлы в каталоге /directory/to/search и во всех его подкаталогах, имеющих расширение .wav переименуйте, как ожидалось, попробуйте это:

find /directory/to/search -type f -name "*.wav" -execdir rename 's/(^\d+) /$1. /' {} +

Чтобы стать нечувствительным к регистру:

find /directory/to/search -type f -iname "*.wav" -execdir rename 's/(^\d+) /$1. /' {} +
Другие вопросы по тегам