Назад | Перейти на главную страницу

Переместите файлы в подкаталоги: /img/ab123.jpg -> /img/ab/ab123.jpg

У меня есть веб-сервер Linux с примерно 25 000 изображений в одном каталоге. Все они в нижнем регистре и имеют формат из двух букв, трех цифр и jpg в качестве расширения. Поскольку управлять большим количеством файлов в одной папке становится сложно, я хочу переместить их во вложенные папки на основе первых двух букв имени файла, например:

/images/ab123.jpg --> /images/ab/ab123.jpg
/images/ab383.jpg --> /images/ab/ab383.jpg
/images/sk234.jpg --> /images/sk/sk234.jpg

Мне уже удалось перечислить всего около 250 различных комбинаций букв и создать подкаталоги:

ls | awk '{print substr($0,0,2)}' | uniq | xargs mkdir

Но мне не удается переместить файлы. Любые идеи?

Bash может извлечь подстроки за вас.

Вот однострочный текст, который предполагает, что целевые каталоги уже существуют:

cd /images; for f in *.jpg; do mv "$f" "${f:0:2}"; done

Этот небольшой скрипт создает каталоги за вас и выполняет действия.

cd /images &&
for f in *.jpg
do
    pre=${f:0:2}
    if [[ ! -d $pre ]]
    then
        mkdir "$pre"
    fi
    mv "$f" "$pre"
done

Многие файлы, поэтому давайте избегать подстановки в пользу find (1): И я использую Zsh как оболочку: остается проблема с именами файлов, содержащими двойные кавычки

find  -maxdepth 1  -type f -exec zsh -c 'a="{}";b=${a:0:4}; mkdir -p $b; mv -t $b $a'   \;

Попробуйте с

for i in $(find . -type f -maxdepth 1); do mv $i $(echo $i|awk '{print substr($0,0,2)}');done

Я считаю, что самый простой способ - использовать rename команда с соответствующим регулярным выражением:

rename 's/^([a-zA-Z]{2})/$1\/$&/' *.jpg

Описание:

$& - its original filename,

$1 - matched 2 first letters, used here as directory name