У меня есть папка, которая содержит папки, которые содержат файлы вида
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?
решение1
Если вы действительно хотите это сделать"с башем", затем
find . -name '*.wcr' -execdir bash -c '
shopt -s extglob; for f; do echo mv -- "$f" "${f/_+([0-9-])_/_}"; done
' bash {} +
Это основано на расширенном шаблоне +([0-9-])
, который соответствует одному или нескольким вхождениям символов в наборе.[0-9-]
Вы можете сделать замену более конкретной, например, ${f/_2017+([0-9-])_/_}
если простое сопоставление цифр и тире слишком общее.
Примечание: удалите echo
как только вы убедитесь, что он делает то, что вам нужно.
решение2
Используйте find
+prename
(Переименование Perl) команды:
find yourfolder -type f -name "*.wcr" -exec prename 's/^(.+)_[0-9]{4}-[0-9]{2}-[0-9]{2}[^_]+(_.*)$/$1$2/' {} +
Чтобы просмотреть prename
результат без действия, добавьте -n
опцию (вывести имена файлов, которые нужно переименовать, но не переименовывать):
man rename
[0-9]{4}-[0-9]{2}-[0-9]{2}
- образец, указывающий надата-подобная подстрока (например2017-05-26
)
решение3
Используяпереименовать perlкоманда (любой вариант, но не util-linux rename
):
find . -type f -name \*.wcr -exec rename 's/_\d{4}-(\d{2}-){2}-(\d{2}-){3}\d+_/_/' {} +
решение4
Если файлы всегда находятся на одном уровне каталога, то вы можете перебрать их с помощью чего-то вроде for x in */*_20*_*
. Какой шаблон использовать, зависит от того, какие еще файлы могут присутствовать, которые вы не хотите переименовывать. Шаблон, который я только что привел, предполагает, что дата начинается с 20
и что все файлы, имя которых содержит _20
и еще один символ отмены после этого, должны быть переименованы.
Вы можете выполнить переименование с помощью цикла оболочки, используярасширение параметраконструкции для создания нового имени файла.
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*_*; …
.шаблон**
соответствует любой глубине каталога, если globstar
включено. Это также работает в bash 4.0–4.2 с оговоркой, что он также проходит по символическим ссылкам на каталоги. Это также работает в zsh и ksh, без оговорки, из коробки в zsh и с set -o globstar
в ksh.