名前が日付であるフォルダー、つまりYYYYMMDDを年、月、日付のフォルダー階層に置き換える方法は?


8

名前に日付を含むフォルダのリストがあります。日付の形式はYYYYMMDDです(例:20150129)。これらのフォルダ内には、その特定の日付に関連するテキストドキュメントがあります。

年から月までのフォルダー階層でそれらを再構築し、テキストドキュメントを階層の下の対応する「日付」フォルダーに移動したいと思います。

言い換えれば、「ルート」フォルダに2015年のような年にちなんで名前を付け、01のような月で名前が付けられたサブフォルダを作成してから、対応するテキストドキュメントを保持する29のような日付で名前が付けられたサブフォルダをさらに作成します。 。

だから、パスは次のようになります2015/01/29/file.txt2015>01>29>file.txt

Automatorを確認しましたが、間違っている可能性がありますが、このようなことは不可能であるようです。知りたいのですが...

  1. たとえばAutomatorワークフローなど、一般の人が理解できるこの問題の簡単な解決策はありますか、またはこれには端末コマンドと正規表現の理解が必要ですか?

  2. 実際に解決策がある場合、この問題をどのように解決しますか?


この質問を「広すぎる」として締めくくる投票者に、なぜですか。この質問の「広すぎる」とは何ですか?
user3439894

これらのYYYYMMDDフォルダーはすべて1つのマスターフォルダー内に直接ありますか、それともより広い階層に分散していますか?
ノーヒルサイド

@patrix私の場合、それらはすべて同じディレクトリまたはマスターフォルダーにあります
davidjnatarajan

回答:


8

これらすべてのYYYYMMDDフォルダが、実行できる同じ親ディレクトリの一部であると想定します

cd PARENT_DIRECTORY
for d in */; do
    [[ $d =~ [0-9]{8}/ ]] || continue
    mkdir -p -- "${d:0:4}/${d:4:2}"
    mv -- "$d" "${d:0:4}/${d:4:2}/${d:6:2}"
done
  • for d in */; doループは、すべてのディレクトリエントリ、末尾の読み込み/のみのディレクトリ名が実際に一致することを保証します
  • [[ $d =~ [0-9]{8}/ ]] 現在のエントリが8桁かどうかをテストし、そうでない場合は次のエントリに進みます
  • ${d:0:4}/${d:4:2}/${d:6:2}内のパラメータ展開bashを使用して、新しいパスを含む文字列を作成します
  • --両方mkdirmv、ディレクトリまたはファイル名がで始まる場合の問題を防ぎます-。これはここでは起こりえませんが、とにかくそれはおそらく良い習慣です。

元のスクリプトを改善する方法についてのアイデアを提供してくれた@terdonと@ user3439894に感謝します。


答えをありがとう、これは完璧に機能します!このソリューションは@grgarsideが提供するソリューションよりも優れていると思います。何千ものテキストドキュメントを含む大規模なコーパスを処理する場合は特に、はるかに高速だからです。
davidjnatarajan 2017

8

ターミナルでは以下を使用できます。cd含むフォルダに移動し、次のコマンドを実行します。

find . -type f -exec bash -c \
  'F=$(sed -E "s#^\./([0-9]{4})([0-9]{2})([0-9]{2})#\1/\2/\3#" <<< $1);\
  mkdir -p -- $(dirname "$F");\
  mv -- "$1" "$F"' - {} \;

find . -type f現在のディレクトリ内のすべてのファイルを再帰的に取得します。
-exec bash -cシェルを開いて次のコマンドを実行します。
F=$(…)サブシェルを開き、ファイルパスでsedを使用して、フォルダーへのパスを操作します。
^\./([0-9]{4})([0-9]{2})([0-9]{2})は、次のように3つのキャプチャグループを持つ正規表現です。 は、各キャプチャグループ(など)がで区切られている置換です。ファイルを移動するディレクトリを作成します。各ファイルを対応するフォルダに移動します。
\1/\2/\3\1/
mkdir -p -- $(dirname "$F")
mv -- "$1" "$F"

これにより、左側の階層が取得され、右側の階層に変換されます。

├── 20170201               └── 2017
   └── abcdefghij             ├── 02
└── 20170302                      └── 01
    └── abcdefghij 2                  └── abcdefghij
                               └── 03
                                   └── 02
                                       └── abcdefghij 2

日付を名前として含むフォルダーに他のファイルがある場合、それらはフォルダーであるかのように移動されます。これを防ぐには、2行目を次のように置き換えます。

  'F=$(sed -E "s#^\./([0-9]{4})([0-9]{2})([0-9]{2})(?:/.+)#\1/\2/\3#" <<< $1);\

(?:/.+)パスは、したがってファイルで親ディレクトリ内の子なしでは何も無視して、その後のコンポーネントを持っていることを保証します。


@klanomath regex101.com
grg

@grgarside Thanx
クラノマス2017
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.