Как использовать форматирование строки bash, чтобы изменить формат даты?

У меня есть много файлов, которые названы как: MM-DD-YYYY.pdf, Я хочу переименовать их как YYYY-MM-DD.pdf Я уверен, что есть немного магии Баша, чтобы сделать это. Что это?

4 ответа

Решение

Для файлов в текущем каталоге:

for name in ./??-??-????.pdf; do
    if [[ "$name" =~ (.*)/([0-9]{2})-([0-9]{2})-([0-9]{4})\.pdf ]]; then
        echo mv "$name" "${BASH_REMATCH[1]}/${BASH_REMATCH[4]}-${BASH_REMATCH[3]}-${BASH_REMATCH[2]}.pdf"
    fi
done

Рекурсивно, в или под текущим каталогом:

find . -type f -name '??-??-????.pdf' -exec bash -c '
    for name do
        if [[ "$name" =~ (.*)/([0-9]{2})-([0-9]{2})-([0-9]{4})\.pdf ]]; then
            echo mv "$name" "${BASH_REMATCH[1]}/${BASH_REMATCH[4]}-${BASH_REMATCH[3]}-${BASH_REMATCH[2]}.pdf"
        fi
    done' bash {} +

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

shopt -s globstar

for name in **/??-??-????.pdf; do
    if [[ "$name" =~ (.*)/([0-9]{2})-([0-9]{2})-([0-9]{4})\.pdf ]]; then
        echo mv "$name" "${BASH_REMATCH[1]}/${BASH_REMATCH[4]}-${BASH_REMATCH[3]}-${BASH_REMATCH[2]}.pdf"
    fi
done

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

Префиксы кода mv с echo для безопасности. Чтобы фактически переименовать файлы, удалите echo (но запустить хотя бы один раз с echo чтобы увидеть, что он делает то, что вы хотите).

Пример прямого подхода из командной строки:

$ ls
10-01-2018.pdf  11-01-2018.pdf  12-01-2018.pdf
$ ls [0-9]*-[0-9]*-[0-9]*.pdf|sed -r 'p;s/([0-9]{2})-([0-9]{2})-([0-9]{4})/\3-\1-\2/'|xargs -n2 mv
$ ls
2018-10-01.pdf  2018-11-01.pdf  2018-12-01.pdf

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

ls + sed Результатом является комбинированный вывод, который состоит из последовательности old_file_name и new_file_name.

Наконец, мы пропускаем полученную подачу через xargs чтобы получить эффективное переименование файлов.

От xargs мужчина:

-n число Выполнить команду, используя как можно больше стандартных входных аргументов, максимум до числа аргументов.

Для этих простых имен файлов, используя более подробный шаблон, вы можете немного упростить тело цикла:

twodigit=[[:digit:]][[:digit:]]
fourdigit="$twodigit$twodigit"
for f in $twodigit-$twodigit-$fourdigit.pdf; do
  IFS=- read month day year <<< "${f%.pdf}"
  mv "$f" "$year-$month-$day.pdf"
done

Это в основном ответ @Kusalananda, но без многословия сопоставления регулярных выражений.

Вы можете использовать следующую команду, очень klashxx на klashxx:

for f in *.pdf; do echo "$f"; mv "$f" "$(echo "$f" | sed 's@\(..\)-\(..\)-\(....\)@\3-\2-\1@')"; done

до:

ls *.pdf
12-01-1998.pdf  12-03-2018.pdf

после:

ls *.pdf
1998-01-12.pdf  2018-03-12.pdf

Также, если у вас есть другие pdf файлы, которые не соответствуют этому формату в вашей папке, вы можете выбрать только те файлы, которые соответствуют формату: MM-DD-YYYY.pdf Для этого используйте следующую команду:

for f in `find . -maxdepth 1 -type f -regextype sed -regex './[0-9]\{2\}-[0-9]\{2\}-[0-9]\{4\}.pdf' | xargs -n1 basename`; do echo "$f"; mv "$f" "$(echo "$f" | sed 's@\(..\)-\(..\)-\(....\)@\3-\2-\1@')"; done

Пояснения:

  • find . -maxdepth 1 -type f -regextype sed -regex './[0-9]\{2\}-[0-9]\{2\}-[0-9]\{4\}.pdf Эта команда поиска будет искать только те файлы в текущем рабочем каталоге, которые соответствуют вашему синтаксису, и извлекать их базовое имя (удалите ./ вначале папки и другие типы файлов, которые будут иметь одинаковые имена, не учитываются, другие *.pdf файлы также игнорируются.

  • for each file Вы делаете перемещение, и полученное имя файла вычисляется с использованием sed и обратной ссылки на 3 группы для MM,DD и YYYY.

Другие вопросы по тегам