Как заменить часть даты в имени файла на текущую дату - PullRequest
0 голосов
/ 02 мая 2019

Как заменить только часть даты на текущую дату всех файлов, присутствующих в директории в unix.

Путь к папке: C:/shan

Примеры файлов:

CN_Apria_837p_20180924.txt  
DN_Apria_837p_20150502.txt  
GN_Apria_837p_20160502.txt  
CH_Apria_837p_20170502.txt  
CU_Apria_837p_20180502.txt  
PN_Apria_837p_20140502.txt  
CN_Apria_837p_20101502.txt  

Желаемый результат должен быть:

CN_Apria_837p_20190502.txt  
DN_Apria_837p_20190502.txt  
GN_Apria_837p_20190502.txt  
CH_Apria_837p_20190502.txt  
CU_Apria_837p_20190502.txt  
PN_Apria_837p_20190502.txt  
CN_Apria_837p_20190502.txt

Редактировать:

Я совершенно новичок в сценариях Unix Sell.Я попробовал это ниже, однако это не работает.

#!/bin/bash

for i in ls $1 | grep -E '[0-9]{4}-[0-9]{2}-[0-9]{2}'
do
  x=echo $i | grep -oE '[0-9]{4}-[0-9]{2}-[0-9]{2}'
  y=echo $i | sed "s/$x/$(date +%F)/g"
  mv $1/$i $1/$y 2>/dev/null #incase if old date is same as current date
done

Ответы [ 3 ]

0 голосов
/ 02 мая 2019

Я бы использовал здесь регулярные выражения. С man-страницы bash:

Доступен дополнительный бинарный оператор = ~, с тем же приоритет как == и! =. Когда это используется, строка справа оператора считается расширенным регулярным выражением и соответствует соответственно (как в регулярном выражении (3)). Возвращаемое значение равно 0, если строка соответствует шаблону, и 1 в противном случае. .... Подстроки
сопоставленные заключенными в скобки подвыражениями в регулярном Выражения сохраняются в переменной массива BASH_REMATCH. ... Элемент BASH_REMATCH с indexn является частью строка, соответствующая n-му заключенному в скобки подвыражению.

Следовательно, предполагая, что переменная x содержит имя одного из файлов под вопросом код

if [[ $x =~ ^(.*_)[0-9]+([.]txt$) ]]
then
  mv "$x" "$BASH_REMATCH[1]$(date +%Y%m%d)$BASH_REMATCH[2]"
fi

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

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

0 голосов
/ 02 мая 2019

Попробуйте это Shellcheck -чистый код:

#! /bin/bash -p

readonly dir=$1

shopt -s nullglob  # Make glob patterns that match nothing expand to nothing

readonly dateglob='20[0-9][0-9][0-9][0-9][0-9][0-9]'
currdate=$(date '+%Y%m%d')

# shellcheck disable=SC2231
for path in "$dir"/*_${dateglob}.* ; do
    name=${path##*/}
    newname=${name/_${dateglob}./_${currdate}.}
    if [[ $newname != "$name" ]] ; then
        newpath="$dir/$newname"
        printf "%q -> %q\\n" "$path" "$newpath"
        mv -i -- "$path" "$newpath"
    fi
done
  • shopt -s nullglob останавливает код, пытающийся обработать путь мусора, если ничто не соответствует шаблону glob в for path in ....
  • Шаблон, присвоенный dateglob, предполагает, что вам не придется обрабатывать даты до 2000 (или после 2099!).Измените его, если это предположение неверно.
  • Строка # shellcheck ... предназначена для предотвращения Shellcheck предупреждения об использовании ${dateglob} без кавычек.Кавычки были бы неправильными в этом случае, потому что они препятствовали бы расширению шаблона glob.
  • Шаблон, используемый для сопоставления имен файлов (*_${dateglob}.*), будет соответствовать гораздо большему количеству форм имени файла, чем приведенные примеры (например, * 1021)*).Возможно, вы захотите изменить его.
  • См. Удаление части строки (BashFAQ / 100 (Как мне манипулировать строками в bash?)) для получения информации об используемых механизмах манипулирования строками Bash.(${path##...}, ${name/...}).
  • Я добавил printf для вывода сведений о том, что перемещается.
  • Параметр -i для mv запрашиваетподтверждение, если файл будет перезаписан.Это оказывается проблемой для файлов примеров, поскольку и CN_Apria_837p_20180924.txt, и CN_Apria_837p_20101502.txt идентичны, за исключением даты, поэтому код пытается переименовать их в одну и ту же вещь.
  • Если какой-либо из файловс датами в именах, имена которых начинаются с '.', код не будет их обрабатывать.Добавьте строку shopt -s dotglob где-нибудь перед циклом, если это является проблемой.
0 голосов
/ 02 мая 2019

Ниже следует сделать это

for f in $(find /path/to/files -name "*_*_*_*.txt")
do 
  newname=$(echo "$f" | sed -r "s/[12][0-9]{3}[01][0-9][0-3][0-9]/$(date '+%Y%m%d')/g")   
  mv "$f" "$newname" 
done
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...