1

Я довольно плохо знаком с сценариями BASH и ищу элегантный способ решения своей задачи:

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

На данный момент мои сценарии выглядят так:

#!/bin/bash
declare -r SOURCEDIR=/some/dir/upload
declare -r DESTBASEDIR=/some/dir/archive

for year in "2009" "2010" "2011" "2012" "2013" "2014"; do
  for letter in {0..9} {A..Z}; do
      mkdir -p ${DESTBASEDIR}/${year}/${letter}
      mv ${SOURCEDIR}/123456789012_${letter}?_??_${year}????.dat ${DESTBASEDIR}/${year}/${letter}/
  done
done

Сценарий делает именно то, что я хочу, но он создает папки назначения, даже если mv не найдет ни одного файла для перемещения туда. Я хотел бы, чтобы mv имел возможность создавать необходимые каталоги, а не создавать их с помощью mkdir.

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

Существует ли простой и элегантный способ создания структуры каталогов на лету, не создавая каталоги enpty?

Спасибо за помощь!

С уважением

Manuel


Версия Гленна Джекмана вдохновила меня на следующие сценарии, которые добиваются цели :)

#!/bin/bash
declare -r SOURCEDIR=/some/dir/upload
declare -r DESTBASEDIR=/some/dir/archive

cd "$SOURCEDIR"
for f in 1234567890_* ; do
  letter=${f:11:1}
  year=${f:21:4}

  dest="$DESTBASEDIR/$year/$letter"

  mkdir -p "$dest"
  mv "$f" "$dest"
done

Обратите внимание, что смещения внутри имени файла сместились с тех пор, как я узнал, начальное число в начале имени файла короче. Данное решение было разработано на моем ложном примере.

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

Данная строка в версии Гленна Джекмана

for f in 123456789012_[A-Z]?_??_[0-9][0-9][0-9][0-9]????.dat ; do

не работал Значение после "in" было интерпретировано как буквальная строка в моем bash. Я не знаю, как "починить" это.

1 ответ1

1

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

cd "$SOURCEDIR"
for f in 123456789012_[A-Z]?_??_[0-9][0-9][0-9][0-9]????.dat ; do
    letter=${f:13:1}
    year=${f:19:4}
    dest="$DESTBASEDIR/$year/$letter"
    mkdir -p "$dest"
    mv "$f" "$dest"
done

Обратите внимание, что использование ${braces} - это не то же самое, что использование "$quotes" если значение переменной содержит пробел

Всё ещё ищете ответ? Посмотрите другие вопросы с метками .