Переименование набора файлов с датой изменило метку времени в конце имени файла?

Можно сделать это довольно легко с awk.

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

awk '
    $3 > maxvals[$2] {lines[$2]=$0; maxvals[$2]=$3}
    END { for (tag in lines) print lines[tag] }
'

Вывод не отсортирован, таким образом передайте по каналу в sort если Вам нужна конкретная сортировка.

14
19.07.2012, 02:34
5 ответов

Быстрая-и-грязная острота Bash для переименования всех (globbed) файлов в текущем каталоге от filename.txt кому: filename.txt-20120620:

for f in *; do mv -- "$f" "$f-$(stat -c %Y "$f" | date +%Y%m%d)"; done

Инициативный компьютерный фанат Bash найдет, что некоторый пограничный случай повреждает его, я уверен.:)

Очевидно, это не делает желательных вещей как проверка, имеет ли файл уже что-то, что похоже на дату в конце.

13
27.01.2020, 19:50
  • 1
    +1, хорошие взгляды. можно сделать его немного более устойчивым при помощи '-', поскольку первый аргумент к mv. принимает меры против filenaes, начинающегося с '-', –  cas 18.07.2012, 06:28
  • 2
    +1, хорошие взгляды. можно сделать его немного более устойчивым при помощи '-', поскольку первый аргумент к mv. принимает меры против filenaes, начинающегося с '-', –  cas 18.07.2012, 06:28
  • 3
    Какой date реализация - это? Мой GNU date кажется, не обрабатывает вход. –  manatwork 19.07.2012, 10:33
  • 4
    coreutils 8.4 на RHEL 6. –  jgoldschrafe 19.07.2012, 15:37
  • 5
    @jgoldschrafe, действительно ли Вы уверены, что кодируют правильно работы для Вас? pastebin.com/nNYubf3A –  manatwork 19.07.2012, 18:00
  • 6
    хорошая выгода manatwork. моя дата GNU 8.13 не поддерживает чтение из stdin также. Это действительно поддерживает использование ультрасовременного времени файла с "-r" - например, "дата + %Y%m%d-r $f", таким образом, статистика даже не необходима в данном случае. –  cas 20.07.2012, 03:45

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

Можно сохранить этот сценарий как что-то как "modif_date.sh" и сделать его исполняемым файлом. Мы вызываем его с целевым каталогом как аргумент:

modif_date.sh txt_collection

Где "txt_collection" является названием каталога, где у нас есть все файлы, которые мы хотим переименовать.

#!/bin/sh

# Override any locale setting to get known month names
export LC_ALL=c
# First we check for the argument
if [ -z "$1" ]; then
    echo "Usage: $0 directory"
    exit 1
fi

# Here we check if the argument is an absolute or relative path. It works both ways
case "${1}" in
  /*) work_dir=${1};;
  *) work_dir=${PWD}/${1};;
esac

# We need a for loop to treat file by file inside our target directory
for i in *; do
    # If the modification date is in the same year, "ls -l" shows us the timestamp.
    # So in this case we use our current year. 
    test_year=`ls -Ggl "${work_dir}/${i}" | awk '{ print $6 }'`
    case ${test_year} in *:*) 
        modif_year=`date '+%Y'`
        ;;
    *)
        modif_year=${test_year}
        ;;
    esac
    # The month output from "ls -l" is in short names. We convert it to numbers.
    name_month=`ls -Ggl "${work_dir}/${i}" | awk '{ print $4 }'`
    case ${name_month} in
            Jan) num_month=01 ;;
            Feb) num_month=02 ;;
        Mar) num_month=03 ;;
        Apr) num_month=04 ;;
        May) num_month=05 ;;
        Jun) num_month=06 ;;
        Jul) num_month=07 ;;
        Aug) num_month=08 ;;
        Sep) num_month=09 ;;
        Oct) num_month=10 ;;
        Nov) num_month=11 ;;
        Dec) num_month=12 ;;
        *) echo "ERROR!"; exit 1 ;;
    esac
    # Here is the date we will use for each file
    modif_date=`ls -Ggl "${work_dir}/${i}" | awk '{ print $5 }'`${num_month}${modif_year}
    # And finally, here we actually rename each file to include
    # the last modification date as part of the filename.
    mv "${work_dir}/${i}" "${work_dir}/${i}-${modif_date}"
done
1
27.01.2020, 19:50
  • 1
    прочитал страницу справочника для статистики (1), чтобы узнать, как можно уменьшить сценарий приблизительно 3/4... большая часть вышеупомянутого изобретает велосипед. в частности, 'статистика-c %Y' даст Вам время изменения файла в секундах с эпохи (01.01.1970 0:00:00). Это может затем использоваться в качестве входа до настоящего времени (1) для форматирования метки времени как требуется. см. ответ jgoldschrafe выше для примера. Достаточно ярмарка –  cas 18.07.2012, 08:56
  • 2
    @CraigSanders, который позитивный аспект - то, что этот сценарий работает под операционными системами кроме Linux, которые имеют другое stat утилита или ни один вообще. –  Gilles 'SO- stop being evil' 19.07.2012, 03:42
  • 3
    Обратите внимание что, анализируя вывод ls не надежно. На некоторых вариантах Unix пользователь и названия группы могут содержать пробелы, которые отбросят выравнивание столбцов даты. –  Gilles 'SO- stop being evil' 19.07.2012, 03:48
  • 4
    @giles: верный, но любой разумный :-) установил бы GNU coreutils (и все другие инструменты GNU) в любой системе не-Linux. Это - самый легкий способ получить не только хороший набор инструментов пространства пользователя, но также и непротиворечивое множество независимо от базового ядра. –  cas 19.07.2012, 07:54
  • 5
    (Cont’d) …   (5)  Another ошибка: это предполагает что любая дата/время, отображенная ls поскольку дата и время (а не дата и год) должна быть в текущем году.   Это не верно.   Это находится за прошлые шесть месяцев; это могло быть в предшествующем году (например, 27 сентября 2016 в течение 31 декабря 2016 в течение прошлых шести месяцев).   (6)  At риск бессмысленно повторения Wiki Greg (который @Gilles, уже процитированный), имена файлов, которые содержат новую строку (строки) и пробелы, могут заставить это перестать работать.   …   (Cont’d) –  G-Man Says 'Reinstate Monica' 27.03.2017, 22:41

вот версия остроты goldschrafe что:

  • не использует статистику
  • работы с более ранними версиями даты GNU
  • правильно справляется с любыми пробелами в именах файлов
  • также справляется с именами файлов, начинающимися с тире

    for f in *; do mv -- "$f" "$f-$(date -r "$f" +%Y%m%d)"; done

18
27.01.2020, 19:50
  • 1
    Необходимо сделать его date -r "$f" +%Y%m%d или это не будет работать если POSIXLY_CORRECT находится в среде. Обычно опции должны пойти перед другими аргументами. –  Stéphane Chazelas 01.09.2015, 12:44
  • 2
    это должно быть "корректным ответом" –  invalidusername 02.03.2016, 11:10
  • 3
    Конечно, Вам не нужны фигурные скобки в "${f}". –  G-Man Says 'Reinstate Monica' 24.03.2017, 04:57
  • 4
    шахты, но как Вы сделали бы его таким образом, что даты мы предварительно ожидали, например, "Ymd-имя-файла"? –  timebandit 10.02.2018, 11:30

Обязательная zsh острота (не считающий одноразовую загрузку дополнительных компонентов):

zmodload zsh/stat
autoload -U zmv
zmv -n '(*)' '$1-$(stat -F %Y%m%d +mtime -- $1)'

Мы используем stat встроенный от zsh/stat модуль, и zmv функция для переименования файлов. И вот дополнительное, которое помещает дату перед расширением, если таковые имеются.

zmv -n '(*)' '$1:r-$(stat -F %Y%m%d +mtime -- $1)${${1:e}:+.$1:e}'
2
27.01.2020, 19:50

Вот версия лайнера -Каса, (основанная на лайнере Гольдшрафа )расширенный сидемпотентностью ,

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

Используйте случай -:полезно, если вы добавляете новые файлы в каталог и хотите добавить префикс даты и времени к тем, у которых его еще нет.

for f in * ; do
  if [[ "$f" != ????-??-??' '??:??:??' - '* ]]; then
    mv -v -- "$f" "$(date -r "$f" +%Y-%m-%d' '%H:%M:%S) - $f" ;
  fi;
done
0
27.01.2020, 19:50

Теги

Похожие вопросы