如何根据文件名第一个字母将文件组织到 AZ 文件夹中

Par*_*rto 15 command-line files

我正在寻找一种方法(最好是终端)通过它们的第一个字母来组织 1000 多种字体。

基本上创建目录,A-Z, #然后根据文件名的第一个字符将字体文件移动到这些目录。以数字 [0-9] 或其他特殊字符开头的字体要移动到#目录中。

Jac*_*ijm 13

一个晚期的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))
Run Code Online (Sandbox Code Playgroud)

如何使用

  1. 将脚本复制到一个空文件中,另存为 move_files.py
  2. 以目录为参数运行它:

    python3 /path/to/move_files.py /path/to/files
    
    Run Code Online (Sandbox Code Playgroud)

如果确实需要,脚本只会创建(子)目录(-ies)(大写)

解释

剧本:


Dav*_*ter 11

只需两个命令和两个正则表达式即可轻松阅读代码:

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

如果您有大量文件要移动,太多而无法放入进程参数列表(是的,有一个限制,可能只有几千字节),您可以使用不同的命令和管道生成文件列表以prename,例如:

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

[[:alnum:]]?*如果没有文件与 glob 模式匹配,这有一个额外的好处,即不尝试移动文字文件名。find还允许比 shell globbing 多得多的匹配条件。另一种方法是设置nullglobshell 选项并关闭prename. 1

在这两种情况下,删除-n开关以实际移动文件,而不仅仅是显示它们将如何移动。

附录:您可以再次删除空目录:

rmdir --ignore-fail-on-non-empty '#' {a..z}
Run Code Online (Sandbox Code Playgroud)

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


Zan*_*nna 8

我没有想出一个很好的方法来使目录名称大写(或用大写字母移动文件),尽管之后您可以使用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
Run Code Online (Sandbox Code Playgroud)

或更易读:

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
Run Code Online (Sandbox Code Playgroud)

echo测试后删除以实际移动文件

进而

rename -n 'y/[a-z]/[A-Z]/' *
Run Code Online (Sandbox Code Playgroud)

-n如果测试后看起来不错,请删除并再次运行。

  • 您可以使用 `if [[ -d "${i^}" ]]` 将变量 `i` 设为大写,并在开头使用 `mkdir {A..Z}`。 (2认同)

mur*_*uru 8

如果你不介意 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'
Run Code Online (Sandbox Code Playgroud)

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
Run Code Online (Sandbox Code Playgroud)

在没有echoinmmv定义的情况下再次运行以实际执行移动。


Arr*_*cal 7

包含字体的目录中的以下命令应该可以工作,如果要从字体存储目录之外使用,请更改for f in ./*for f in /directory/containing/fonts/*. 这是一种非常基于 shell 的方法,所以速度很慢,而且也是非递归的。如果存在以匹配字符开头的文件,这只会创建目录。

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
Run Code Online (Sandbox Code Playgroud)

作为一个衬垫,再次从字体存储目录中:

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
Run Code Online (Sandbox Code Playgroud)

使用 find 的方法,具有类似的字符串操作,使用 bash 参数扩展,这将是递归的,并且应该比纯 shell 版本快一些:

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' \;
Run Code Online (Sandbox Code Playgroud)

或更易读:

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' \;
Run Code Online (Sandbox Code Playgroud)


小智 5

使用tr, thenmkdir和 将每个文件名映射到目录名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'
Run Code Online (Sandbox Code Playgroud)