Как я могу организовать файлы на основе их имени файла, сначала обозначают буквами в папки A-Z

Я ищу путь (предпочтительно терминал) для организации более чем 1 000 шрифтов их первой буквой.

В основном создайте каталоги A-Z, # затем переместите файлы шрифтов в те каталоги на основе их имени файла первый символ. Шрифты, которые начинаются с номеров [0-9] или других специальных символов, которые будут перемещены в # каталог.

15
задан 10 January 2017 в 02:44

6 ответов

Последняя опция Python:

#!/usr/bin/env python3
import os
import sys
import shutil

def path(dr, f): return os.path.join(dr, f)

dr = sys.argv[1]
for f in os.listdir(dr):
    fsrc = path(dr, f)
    if os.path.isfile(fsrc):
        s = f[0]; target = path(dr, s.upper()) if s.isalpha() else path(dr, "#")
        if not os.path.exists(target):
            os.mkdir(target)
        shutil.move(fsrc, path(target, f))

Как использовать

  1. Скопируйте сценарий в пустой файл, сохраните его как move_files.py
  2. Выполните его с каталогом как аргумент:

    python3 /path/to/move_files.py /path/to/files
    

Сценарий только создаст (sub) каталог (-ies) (верхний регистр), если он будет на самом деле необходим

Объяснение

Сценарий:

  • перечисляет файлы, добирается, первый символ (определяет sourcepath):

    for f in os.listdir(dr):
        s = f[0]; fsrc = path(dr, f)
    
  • проверки, если объект является файлом:

    if os.path.isfile(fsrc):
    
  • определяет целенаправленную папку или для того, если первый символ является альфой или нет:

    target = path(dr, s.upper()) if s.isalpha() else path(dr, "#")
    
  • проверки, если папка уже существует или нет, создают ее если нет:

    if not os.path.exists(target):
        os.mkdir(target)
    
  • перемещает объект в его соответствующую папку:

    shutil.move(fsrc, path(target, f))
    
13
ответ дан 23 November 2019 в 02:38

Если Вы не возражаете против zsh, функции и нескольких zmv команды:

mmv() {echo mkdir -p "${2%/*}/"; echo mv -- "$1" "$2";}
autoload -U zmv
zmv -P mmv '([a-zA-Z])(*.ttf)' '${(UC)1}/$1$2'
zmv -P mmv '([!a-zA-Z])(*.ttf)' '#/$1$2'

Эти mmv функция делает каталог и перемещает файл. zmv затем обеспечивает сопоставление с образцом и замену. Во-первых, перемещая имена файлов, запускающиеся с алфавита, затем все остальное:

$ zmv -P mmv '([a-zA-Z])(*.ttf)' '${(UC)1}/$1$2'
mkdir -p A/
mv -- abcd.ttf A/abcd.ttf
mkdir -p A/
mv -- ABCD.ttf A/ABCD.ttf
$ zmv -P mmv '([!a-zA-Z])(*.ttf)' '#/$1$2'
mkdir -p #/
mv -- 123.ttf #/123.ttf
mkdir -p #/
mv -- 七.ttf #/七.ttf

Выполнение снова без echo в mmv определение для фактического выполнения перемещения.

8
ответ дан 23 November 2019 в 02:38

Я не разрабатывал хороший способ сделать верхний регистр имен каталогов (или перемещать файлы с прописными буквами), хотя Вы могли сделать это впоследствии с rename...

mkdir {a..z} \#; for i in {a..z}; do for f in "$i"*; do if [[ -f "$f" ]]; then echo mv -v -- "$f" "$i"; fi; done; done; for g in [![:alpha:]]*; do if [[ -f "$g" ]]; then echo mv -v -- "$g" \#; fi; done

или больше четко:

mkdir {a..z} \#; 
for i in {a..z}; do 
  for f in "$i"*; do
    if [[ -f "$f" ]]; then 
      echo mv -v -- "$f" "$i"; 
    fi 
  done
done
for g in [![:alpha:]]*; do 
  if [[ -f "$g" ]]; then 
    echo mv -v -- "$g" \#
  fi
done

Удаляют echo после тестирования для фактического перемещения файлов

, И затем

rename -n 'y/[a-z]/[A-Z]/' *

удаляют -n, если это выглядит хорошим после тестирования и выполненным снова.

8
ответ дан 23 November 2019 в 02:38

Отобразите каждое имя файла на имя каталога с помощью tr, затем mkdir и mv:

find /src/dir -type f -print0 |
xargs -0 -I{} bash -c \
  'dir=/dest/$(basename "{}" | cut -c1 | tr -C "a-zA-Z\n" "#" | tr "a-z "A-Z"); mkdir -p $dir; mv "{}" $dir'
5
ответ дан 23 November 2019 в 02:38

Следующие команды в рамках каталога, содержащего шрифты, должны работать, если Вы хотите использовать снаружи каталога хранилища шрифта, изменение for f in ./* к for f in /directory/containing/fonts/*. Это - очень основанный на оболочке метод, настолько довольно медленный, и также нерекурсивно. Это только создаст каталоги, если будут файлы, которые запускаются с символа соответствия.

target=/directory/to/store/alphabet/dirs
mkdir "$target"
for f in ./* ; do 
  if [[ -f "$f" ]]; then 
    i=${f##*/}
    i=${i:0:1}
    dir=${i^}
    if [[ $dir != [A-Z] ]]; then 
      mkdir -p "${target}/#" && mv "$f" "${target}/#"
    else
      mkdir -p "${target}/$dir" && mv "$f" "${target}/$dir"
    fi
  fi
done

Как один лайнер, снова из каталога хранилища шрифта:

target=/directory/to/store/alphabet/dirs; mkdir "$target" && for f in ./* ; do if [[ -f "$f" ]]; then i=${f##*/}; i=${i:0:1} ; dir=${i^} ; if [[ $dir != [A-Z] ]]; then mkdir -p "${target}/#" && mv "$f" "${target}/#"; else mkdir -p "${target}/$dir" && mv "$f" "${target}/$dir" ; fi ; fi ; done

использование метода А находит, с подобной обработкой строк, с помощью расширения параметра удара, которое будет рекурсивным, и должно быть несколько более быстрым, чем чистая версия оболочки:

find . -type f -exec bash -c 'target=/directory/to/store/alphabet/dirs ; mkdir -p "$target"; f="{}" ; i="${f##*/}"; i="${i:0:1}"; i=${i^}; if [[ $i = [[:alpha:]] ]]; then mkdir -p "${target}/$i" && mv "$f" "${target}/$i"; else mkdir -p "${target}/#" && mv "$f" "${target}/#"; fi' \;

Или больше четко:

find . -type f -exec bash -c 'target=/directory/to/store/alphabet/dirs 
   mkdir -p "$target"
   f="{}"
   i="${f##*/}"
   i="${i:0:1}"
   i=${i^}
   if [[ $i = [[:alpha:]] ]]; then 
      mkdir -p "${target}/$i" && mv "$f" "${target}/$i"
   else
      mkdir -p "${target}/#" && mv "$f" "${target}/#"
   fi' \;
7
ответ дан 23 November 2019 в 02:38

Игравший в гольф кодом все же читаемый со всего двумя командами и двумя регулярными выражениями:

mkdir -p '#' {a..z}
prename -n 's|^[[:alpha:]]|\l$&/$&|; s|^[0-9]|#/$&|' [[:alnum:]]?*

Если у Вас есть огромная сумма файлов для перемещения, слишком многие для вписывания в список аргументов процесса (да, существует предел, и это могут быть всего несколько килобайтов), можно генерировать список файлов с другой командой и каналом это к prename, например:

find -mindepth 1 -maxdepth 1 -name '[[:alnum:]]?*' -printf '%f\n' |
prename -n 's|^[[:alpha:]]|\l$&/$&|; s|^[0-9]|#/$&|'

Это обладает дополнительным преимуществом не попытки переместить литеральное имя файла [[:alnum:]]?* если никакие файлы не соответствуют шаблону шарика. find также позволяет намного больше критериев соответствия, чем оболочка globbing. Альтернатива должна установить nullglob опция оболочки и близко стандартный входной поток prename.1

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

Приложение: можно удалить пустые каталоги снова с:

rmdir --ignore-fail-on-non-empty '#' {a..z}

1 shopt -s nullglob; prename ... <&-

11
ответ дан 23 November 2019 в 02:38

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

Похожие вопросы: