Удалить дату и время рекурсивно из имен файлов

У меня есть папка, которая содержит папки, содержащие файлы формы

resultstatsDF_iris_2017-05-26--21-33-35-437096_methodnr-2_percentage-0.05_seed-0.wcr 

Я хочу удалить дату и время для каждого из них, так что в этом случае получите

 resultstatsDF_iris_methodnr-2_percentage-0.05_seed-0.wcr 

Как это сделать в bash?

Если вы действительно хотите сделать это «с bash» , тогда

 find . -name '*.wcr' -execdir bash -c ' shopt -s extglob; for f; do echo mv -- "$f" "${f/_+([0-9-])_/_}"; done ' bash {} + 

Это зависит от расширенного glob +([0-9-]) который соответствует одному или нескольким вхождениям символов в наборе [0-9-]

Вы могли бы сделать замену более конкретной, например ${f/_2017+([0-9-])_/_} если просто совпадающие цифры и тире слишком общие.

Примечание: удалите echo если вы уверены, что он делает то, что вы хотите.

Используйте команды find + prename (Perl rename):

 find yourfolder -type f -name "*.wcr" -exec prename 's/^(.+)_[0-9]{4}-[0-9]{2}-[0-9]{2}[^_]+(_.*)$/$1$2/' {} + 

Чтобы просмотреть результат prename без действия add -n ( распечатать имена файлов, которые нужно переименовать, но не переименовывать ):

 man rename 

  • [0-9]{4}-[0-9]{2}-[0-9]{2} – шаблон, указывающий на подстроку, 2017-05-26 дате (например, 2017-05-26 )

Использование команды переименования perl (любой вариант, но не rename util-linux):

 find . -type f -name \*.wcr -exec rename 's/_\d{4}-(\d{2}-){2}-(\d{2}-){3}\d+_/_/' {} + 
 for i in ./*/*; do j=`echo "$i" | cut -d'_' -f1-2,4-` mv "$i" "$j" done 

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

Если файлы всегда имеют один уровень на уровне директории, то вы можете перебирать их с помощью чего-то вроде for x in */*_20*_* . Какой шаблон использовать, зависит от того, какие другие файлы могут присутствовать, которые вы не хотите переименовывать. Шаблон, который я только что дал, предполагает, что дата начинается с 20 и что все файлы, чье имя содержит _20 и еще один undescore после этого, должны быть переименованы.

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

 for old_name in ./*/*_20_*_*; do base=${old_name##*/} # remove the directory part prefix=${base%%_20*} # remove everything from _20 suffix=${base#*_20} # remove everything up to _20 suffix=${suffix#*_} # ... then everything before the first remaining _ mv "$old_name" "${old_name%/*}/${prefix}_${suffix}" done 

Если файлы находятся на различной глубине, в bash ≥4.3, вы можете запустить shopt -s globstar затем for x in **/*_20*_*; … for x in **/*_20*_*; … Образец ** соответствует любой глубине каталога, если globstar включен. Это также работает в bash 4.0-4.2 с предостережением о том, что он также пересекает символические ссылки на каталоги. Это также работает в zsh и ksh, без оговорки, из коробки в zsh и с set -o globstar в ksh.