ディレクトリ階層を平面化し、新しいディレクトリ名にディレクトリ名を保存します。

ディレクトリ階層を平面化し、新しいディレクトリ名にディレクトリ名を保存します。

私は基本的にここで始めたいと思います:

.
├── Alan Walker
│   ├── Different World
│   │   ├── 01 Intro.mp3
│   │   ├── 02 Lost Control.mp3
│   │   └── cover.jpg
│   └── Same World
│       ├── 01 Intro.mp3
│       └── 02 Found Control.mp3
├── Aurora
│   └── Infections Of A Different Kind Step 1
│       ├── 01 Queendom.lrc
│       ├── 02 Forgotten Love.lrc
│       └── 03 Gentle Earthquakes.mp3
└── Guns N' Roses
    └── Use Your Illusion I
        ├── 01 Right Next Door To Hell.lrc
        ├── 01 Right Next Door To Hell.mp3
        ├── 02 Dust N' Bones.lrc
        └── 02 Dust N' Bones.mp3

これに関して:

.
├── Alan Walker - Different World
│   ├── 01 Intro.mp3
│   ├── 02 Lost Control.mp3
│   └── cover.jpg
├── Alan Walker - Same World
│   ├── 01 Intro.mp3
│   └── 02 Found Control.mp3
├── Aurora - Infections Of A Different Kind Step 1
│   ├── 01 Queendom.lrc
│   ├── 02 Forgotten Love.lrc
│   └── 03 Gentle Earthquakes.mp3
└── Guns N' Roses - Use Your Illusion I
    ├── 01 Right Next Door To Hell.lrc
    ├── 01 Right Next Door To Hell.mp3
    ├── 02 Dust N' Bones.lrc
    └── 02 Dust N' Bones.mp3

私が見つけた既存のソリューションには、ディレクトリ自体の名前を変更することは含まれていません。 zmvでこれを行うことができればいいでしょうが、どうすればいいかわかりません。

答え1

たぶんこんなことはありませんか?

#!/bin/sh

for topdir in */; do
    topdir_name=$( basename "$topdir" )

    for subdir in "$topdir"/*/; do
        subdir_name=$( basename "$subdir" )

        newdir="$topdir_name - $subdir_name"
        if mkdir "$newdir"; then
            mv "$subdir"/* "$newdir"
            rmdir "$subdir"
        fi
    done

    rmdir "$topdir"
done

これは、現在のディレクトリのすべての最上位ディレクトリ(バンド名)を繰り返します。これらの各ディレクトリに対して、対応するサブディレクトリ(アルバム名)を繰り返します。バンド名とアルバム名のペアごとに新しいディレクトリが作成され、サブディレクトリのファイルがそのディレクトリに移動されます。アルバムサブディレクトリは、元のバンドのトップレベルディレクトリと同様に処理後に削除されます。

rmdirディレクトリに隠しファイル名が含まれている場合、または新しいディレクトリが作成されない場合、呼び出しは失敗します。

完全にテストされていないコードです。ファイルのバックアップコピーから実行します。

答え2

ジッシュ

テストされていません:

zmv -Q '(*)/(*)(/)' '$1 - $2'
rmdir -- *(/^F)

2行目は、以前にファイルがなかったディレクトリを含むすべての空のディレクトリを削除します。この問題は、mvコンテンツが移動されるディレクトリを記録するカスタムラッパーを使用して解決できます。

これは現在のディレクトリのディレクトリへのシンボリックリンクを巡回します。

Linuxの名前変更ユーティリティ

検証されていません。

rename / ' - ' */*/
rmdir -- */ 2>/dev/null

これは現在のディレクトリとそのサブディレクトリのディレクトリにシンボリックリンクを通過します。 2行目は、以前にファイルがなかったディレクトリを含むすべての空のディレクトリを削除します。

Perlの名前変更スクリプト

検証されていません。

prename 's~/~ - ~' */*/
rmdir -- */ 2>/dev/null

これは現在のディレクトリとそのサブディレクトリのディレクトリにシンボリックリンクを通過します。 2行目は、以前にファイルがなかったディレクトリを含むすべての空のディレクトリを削除します。

これは、名前が変更されたディレクトリのみを削除するより洗練された方法です。繰り返しますが、テストされていません。

prename 's~([^/]+)/~$1 - ~ and ++$d{$1}; END {map {rmdir} keys %d}' */*/

答え3

戦略的にファイルを移動するのではなく、現在の構造を維持し、必要な新しい構造へのリンクを作成することを検討しましたか?

戦術的にこれを行うパターンは次のとおりです。

find . -mindepth 2 -maxdepth 2 -type d -print0 | xargs -0n1 bash -c \
  'b=$(basename "$(dirname "$1")"); a=$(basename "$1"); echo ln -s "$1" "$b-$a"' {}
  • find現在の作業ディレクトリ(バンドルを含むディレクトリである必要があります)で、正確に2つのレベルの深さのすべてのディレクトリを見つけます。したがって、2つのレベルの深さはバンド名の下のアルバム名です。1
  • xargsアルバムを含む各パスを使用し、インラインbashスクリプトを呼び出します。
  • bash -c '...'アルバムパスを最初の引数として使用して、パスをバンド($b)とアルバム($a)の2つの部分に分割します。最後に、スクリプトは名前を目的の形式に再組み立てし、新しいディレクトリ名を元のディレクトリに関連付けます。

この場合、リンクは起動したディレクトリと同じディレクトリに作成され、バンド名もそのディレクトリに作成されます。

lnあなたの意図に合わせて上記の戦略を調整して調整する必要があります。mv並べ替えやlnメディアに便利な「ビュー」を作成するには、正しいパスを使用してください。 Bashスクリプトの重要な部分は次のとおりです。

  • $bバンド名。常に引用してください:"$b"
  • $aアルバム名です。常に引用してください:"$a"
  • $1アルバムディレクトリの物理パス。常に引用してください:"$1"

1m{ax,in}depth私はGNUといくつかのBSDがそれをサポートしていると思いますfindが、POSIXはサポートしていません。この場合は、*/*シェル体操または同様のものに依存します。

関連情報