Установите время модификации файла из строки даты, присутствующей в имени файла - PullRequest
1 голос
/ 19 апреля 2019

Я восстанавливаю ряд архивов с датами в их именах, что-то вроде:

user-2018.12.20.tar.xz
user-2019.01.10.tar.xz
user-2019.02.25.tar.xz
user-2019.04.19.tar.xz
...

Я хочу установить дату модификации каждого файла так, чтобы она соответствовала дате в их имени файла, передавая по трубопроводуимена файлов: touch через xargs и использование replace-str для установки дат.

touch -m -t займет дату-время в формате [CCYYMMDDhhmm], но у меня возникли проблемы с заменой встроенного:

find . -name "*.xz" | xargs -I {} touch -m -t $(sed -e 's/\.tar\.xz//g; s/user-//g; s/\.//g; s/\///g; s/$/0000/g' {}) {}

Возвращает touch: invalid date format ‘./user-2018.03.22.tar.xz’, даже если это:

find . -name "*.xz" | sed -e 's/\.tar\.xz//g; s/user-//g; s/\.//g; s/\///g; s/$/0000/g'

Возвращает правильно отформатированные даты, например 201812200000.Я неправильно использую подстановку команд в моей строке замены?

РЕДАКТИРОВАТЬ: Да, простой сценарий может сделать это без проблем.Но вопрос остается ...

Ответы [ 3 ]

4 голосов
/ 19 апреля 2019

Проблема в том, что подстановка команды будет оцениваться один раз при вызове xargs, а не для каждого аргумента.Для этого вам нужно будет создать оболочку:

find . -name "*.xz" \
  | xargs -I {} bash -c 'touch -m --date "$(sed -e "s/\.tar\.xz//;s/user-//g; s/\.//g; s/\///g;" <<< "$1")" "$1"' -- {}

Примечание: xargs не требуется, поскольку вы можете использовать опцию -exec find:

find . -name "*.xz" -exec bash -c 'touch -m --date "$(sed -e "s/\.tar\.xz//;s/user-//g; s/\.//g; s/\///g;" <<< "$1")" "$1"' -- {} \;

PS: маленький цикл for будет более читабельным:

for file in user-*.tar.xz ; do
    # remove prefix and suffix
    date=${file#user-}
    date=${date%.tar.xz}
    # replace dots by /
    date=${date//./\/}

    touch -m --date "${date}" "${file}"
done
4 голосов
/ 19 апреля 2019

Вам не нужны find, sed, xargs или какие-либо сторонние инструменты, а просто используйте встроенные функции регулярного выражения оболочки, чтобы получить метку времени из файла

 for file in *.tar.xz; do
     [ -f "$file" ] || continue
     if [[ $file =~ ^user-([[:digit:]]+).([[:digit:]]+).([[:digit:]]+).tar.xz$ ]]; then
         dateStr="${BASH_REMATCH[1]}${BASH_REMATCH[2]}${BASH_REMATCH[3]}0000"
         touch -m -t "$dateStr"
     fi
 done
3 голосов
/ 20 апреля 2019

Это может сработать для вас (параллельно GNU):

parallel --dryrun touch -m --date '{= s/[^0-9]//g =}' {} ::: *.xz

Если все в порядке, если команды верны, удалите параметр --dryrun.

Альтернатива:

parallel touch -m --date `{= s/user-//;s/\.tar\.xz//;s/\.//g =}' {} ::: *.xz
...