Я довольно плохо знаком с сценариями 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. Я не знаю, как "починить" это.