ファイル名の最初の文字に基づいてファイルをAZフォルダーに整理する方法


15

私は、最初の文字で1000以上のフォントを整理する方法(できれば端末)を探しています。

基本的にディレクトリA-Z, #を作成し、ファイル名の最初の文字に基づいてフォントファイルをそれらのディレクトリに移動します。ディレクトリに移動する数字[0-9]またはその他の特殊文字で始まるフォント#


その文字で始まるファイルがない場合でも、ディレクトリを作成しますか?
17

@Arronical Nope。ファイルがある場合。
パート

4
このリンクがあなたに役立つことを願っていますstackoverflow.com/questions/1251938/…–
Karthickeyan

回答:


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))

使い方

  1. スクリプトを空のファイルにコピーして、名前を付けて保存します move_files.py
  2. ディレクトリを引数として実行します:

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

スクリプトは、実際に必要な場合にのみ(sub)ディレクトリ(-ies)(大文字)を作成します

説明

スクリプト:

  • ファイルをリストし、最初の文字を取得します(ソースパスを定義します):

    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))

やあヤコブ。大文字の最初の文字のチェックはありますか?
パート

@Parto絶対に!どのようにそれが必要ですか?(3.5時間の授業でチェックインできます:)
ジェイコブVlijm

実際にやった。完全な実装。
パート

検討した後、私はいくつかの理由でこの答えに行くことにしました:1)。何が起こっているかの説明。2)。最初の試行で正しく実行答え
Parto

11

2つのコマンドと2つの正規表現だけで、コードゴルフはできますが読み取り可能です。

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:]]?*globパターンに一致するファイルがない場合にリテラルファイル名を移動しようとしないという利点があります。findまた、シェルグロビングよりも多くの一致基準を使用できます。別の方法として、nullglobシェルオプションを設定し、の標準入力ストリームを閉じますprename1

どちらの場合も、-nスイッチを削除して、ファイルの移動方法を示すだけでなく、実際にファイルを移動します。

補遺:次のコマンドで空のディレクトリを再び削除できます:

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

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


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'

この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

echoin mmvの定義なしで再実行して、実際に移動を実行します。


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

またはもっと読みやすい:

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テスト後に問題がなければ削除して、再度実行します。


2
を使用if [[ -d "${i^}" ]]して、変数をi大文字にすることができますmkdir {A..Z}
1

これを試してみましょう
-Parto

@ありがとうございます!あなたがそれをあなた自身の方法で投稿したので、私はそれを残します
-Zanna

@Zannaさまざまな方向からやって来て、文字を繰り返し処理し、検索条件としてそれらを使用したことがないことが気に入っています。findを使用した賢明で高速なソリューションがあるはずですが、それを回避することはできません。
1

Zannaさん、これは大文字で始まるフォントを移動しませんでした。それ以外の場合はうまくいきました。
パート

7

フォントを含むディレクトリ内の次のコマンドが機能するはずです。フォントストレージディレクトリの外部から使用する場合は、に変更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

1つのライナーとして、再びフォントストレージディレクトリ内から:

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

同様の文字列操作を使用して、bashパラメーター展開を使用するfindを使用するメソッドは、再帰的であり、純粋なシェルバージョンよりも多少速くなるはずです。

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' \;

これも機能しました。大文字でも小文字でも。
パート

5

使用して、ディレクトリ名に各ファイル名の地図trそして、mkdirmv

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'

私はこれが本当に好きです。これは、findを使用したいという願いで私が把握していたことの線に沿っています。大文字のディレクトリ名のみを作成し、小文字のファイル名をそれらに移動する方法はありますか?
1

1
tr大文字に変換する別のものを追加しました。
xn。

なぜ再びxargs電話するだけで迂回するのbashですか?findwhileループに出力をパイプ処理し、readレコードごとに処理する方が簡単で読みやすいのではないでしょうか?
デビッドフォースター

良い質問です、@ DavidFoerster。ワンライナーのループに対するバイアスと、より機能的なアプローチの優先度を推測します。しかし、文字列内のbashスクリプトもあまりエレガントではないため、おそらくwhileループバージョン(bit.ly/2j2mhyb)の方が優れていると思います。
xn。

ところで、引数を追加してシェルスクリプト内を参照するようにすると、厄介な{}置換を回避できます。例:。(ファイナルをおxargs$1xargs -0 -n1 -- bash -c 'dir=/dest/$(basename "$1" | ...); ...; mv "$1" "$dir"' __
忘れなく
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.