Пакетный файл перемещается в структуру каталогов на основе имени файла

Я пишу сценарий для перемещения файлов в каталоги на основе имени файла. Файлы имеют yyyyddmm-xxxxxxx.jpg . Желаемая структура каталогов находится в формате 2013/01 Jan/31 . Я не могу правильно определить date с форматом пробела между месяцем и именем месяца. Когда я пытаюсь использовать формат +%Y/%m %b , я получаю это сообщение об ошибке:

date: дополнительный операнд `% b ''

Я пробовал двойные и одинарные кавычки, но безуспешно. Однако date +"%Y/%m %b/%d" отлично работает в sh :

2013/10/27 окт.

Кроме того, есть ли лучший способ генерировать имя каталога, чем использовать переменные MOVEDIRSTR и MOVEDIR (см. Скрипт)?

Вот мой текущий скрипт:

 FLIST=`ls "$IMGDIR" | grep -E '^.*\.jpg$'` # If there are files to move if [ -n "${FLIST}" ]; then # For each file while read -r line; do # Parse filename to YYYY/mm Mmm/Dd echo $line MOVEDIRSTR=`sed -r -e 's:([0-9]{4})([0-9]{2})([0-9]{2}).*:date -d \1-\2-\3 +%Y/%m_%b/%d:' <<< "$line"` MOVEDIR=`$MOVEDIRSTR` # If a directory does not exist, create it [ -d "$ARCHIVEDIR/$MOVEDIR" ] || (mkdir -p "$ARCHIVEDIR/$MOVEDIR") # Move file into YYYY/mm Mmm directory # mv -f "$IMGDIR/$line" "$ARCHIVEDIR/$MOVEDIR" done <<< "$FLIST" fi 

  • Переименуйте только один файл в каждом каталоге, исходя из условия
  • Переименование файла в тот момент, когда он отображается в папке
  • Можно ли разделить файл и добавить части с одинаковым расширением в один лайнер?
  • Лучше ли передавать все файлы в mv или параллельно запускать несколько процессов mv?
  • Вывод NamingVariable для нескольких файлов в сценарии Bash
  • Два раздела жесткого диска с тем же именем приводят к неопределенным каталогам
  • Добавить расширение ко всем файлам в каталоге, содержащем точную строку
  • Переименование пучки файлов с датой, измененной меткой времени в конце имени файла?
  • 3 Solutions collect form web for “Пакетный файл перемещается в структуру каталогов на основе имени файла”

    Вы должны указать формат на сегодняшний день после знака + .

     $ date +"%Y/%m %b" 2013/10 Oct 

    Относительно переменных. $MOVEDIRSTR кажется ненужным.

     MOVEDIR=$(sed -r -e 's:([0-9]{4})([0-9]{2})([0-9]{2}).*:date -d \1-\2-\3 +%Y/%m_%b/%d:' <<< "$line") 

    Поскольку с помощью $FLIST вы разбираете даты из этого каталога, я не вижу более чистого способа.

    ОБНОВЛЕНИЕ # 1

    Учитывая обратную связь OP в комментариях ниже, он использует устройство QNAP и, вероятно, имеет приведенную в действие версию этих команд, предоставленную BusyBox. Если вы посмотрите на команду date так: ls -l /bin/date это, вероятно, ссылка на исполняемый файл busybox или что-то подобное. Эти команды не являются полнофункциональными, следовательно, ваши проблемы.

    Он подтвердил это:

    Возможно Вы правы. Моя дата – это собственный исполняемый файл, но / bin / sed -> busybox

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

    Прежде всего, я бы использовал glob, чтобы избежать разбора ls и получения списка файлов .jpg в этом кольцевом режиме. Во-вторых, вы можете использовать оболочку (без необходимости sed ) для извлечения компонентов даты:

     shopt -s nullglob for file in "$IMGDIR"/*.jpg; do file_name="$(basename file)" printf "%s\n" "$file_name" numbers="${file%-*}" year="${numbers%[0-9][0-9][0-9][0-9]}" monthday="${numbers#[0-9][0-9][0-9][0-9]}" month="${monthday%[0-9][0-9]}" day="${monthday#[0-9][0-9]}" movedir="$(date -d "$year-$month-$day" +"%Y/%m %b/)" movefile="$(date -d "$year-$month-$day" +"%Y/%m %b/%d)" [ -d "$ARCHIVEDIR/$movedir" ] || mkdir -p "$ARCHIVEDIR/$movedir" mv "$file" "$movefile" done 

    Это предполагает, конечно, что ваша команда date имеет достаточно полный набор функций, поскольку вы упомянули, что это отдельный исполняемый файл из BusyBox. Он также сломается, если длина строки даты не составляет 8 цифр.

    см., может ли следующее решить часть извлечения и форматирования даты:

     $ f=20130131-abcdefgh.jpg $ [[ $f =~ ^([[:digit:]]{4})([[:digit:]]{2})([[:digit:]]{2}) ]] $ yyyy=${BASH_REMATCH[1]} $ mm=${BASH_REMATCH[2]} $ dd=${BASH_REMATCH[3]} $ date -d ${yyyy}-${mm}-${dd} +'%Y/%m %b/%d' 2013/01 Jan/31 
    Linux и Unix - лучшая ОС в мире.