web-dev-qa-db-ja.com

すべてのサブフォルダーをディゾルブする方法

フォルダーのすべての直接サブフォルダーのすべてのコンテンツをフォルダー自体に移動し、サブフォルダー(現在は空)を削除するコマンドラインワンライナーはありますか?つまり、フォルダー階層のレベルを削除しますか?

明確にするために、より深いサブフォルダー構造を保持する必要があります。

私はこれに数回遭遇しましたが、これがDolphinの特徴ではなく、他の人が苦労しているものではないように少し失望しました。

これを2つに分割して、サブフォルダーの内容を移動し、サブフォルダーを削除する必要があると思われます。ただし、これには、空の第2レベルのサブフォルダーを削除するという望ましくない副作用がある場合があります。

4
oulenz

実際には実際のワンライナーではありません:

find . -mindepth 2 -maxdepth 2 -print -exec mv --backup=numbered -t . '{}' + \
&& find . -mindepth 1 -maxdepth 1 -type d -empty -delete

最初にサブフォルダー内ですべての深さが2であるものをすべて見つけ、.に移動します。次に、現在のディレクトリですべての空のフォルダを見つけて削除します。

  • 同じ名前のファイル/フォルダーがある場合は、original_filename.~n~(nは1、2、3 ...を意味します)に名前が変更されます。
  • すべての空のサブフォルダーが削除されることに注意してください。

更新:

上記のソリューションに満足できません。警告と問題が多すぎます。たとえば、--backup = numberedが、移動するフォルダーの親フォルダーの名前を変更する場合...

mkdir -p test/test
mv test/test . --backup=numbered
mv: cannot move 'test/test' to './test': No such file or directory

問題を回避するには、一時ディレクトリを使用することをお勧めします。一時ディレクトリは、ファイルをコピーする必要を避けるため、同じファイルシステム上にある必要があります。

tmpdir=$(mktemp -d)
find . -mindepth 2 -maxdepth 2 -print -exec mv -b -t $tmpdir '{}' +
find . -mindepth 1 -maxdepth 1 -type d -empty -delete
mv -b $tmpdir/* .
rm $tmpdir
5
pLumo

空のサブディレクトリを削除しないようにするには、IMOで最も簡単な方法は、一時ディレクトリに移動してから、一時ディレクトリの名前を古いディレクトリに変更することです。問題のディレクトリがfooであり、foo/*/*foo/*にしたいとします。次のようなことをしてください:

tar c --remove-files foo | tar xv --strip-components=2 --backup=t --one-top-level=temp
mv temp foo
  • --remove-filesを使用すると、最初のtarはファイルを処理するときにファイルを削除し、最後にfoo自体を削除します。
  • --strip-components=2を使用すると、2番目のtarは、抽出するパスからfoo/*/を切り捨てるので、foo/a/bbになります。
  • --backup=tcpまたはmvと同じです-番号付きバックアップコピーを作成します。ただし、mvは同じ名前のディレクトリのコピーを作成しますが、tarはディレクトリをマージしてファイルのバックアップを作成します。
  • --one-top-level=temptartempという名前のディレクトリを作成し、そこにファイルを抽出するよう指示します。

例えば:

$ tree bar
bar
├── a
│   ├── c
│   │   └── bar
│   ├── d
│   │   └── bar
│   ├── e
│   │   └── bar
│   └── f
│       └── bar
├── b
│   ├── c
│   │   └── bar
│   ├── d
│   │   └── bar
│   ├── e
│   │   └── bar
│   └── f
│       └── bar
└── c
    ├── c
    │   └── bar
    ├── d
    │   └── bar
    ├── e
    │   └── bar
    └── f
        └── bar

そして、tarコマンドを実行した後:

$ tar c --remove-files bar | tar xv --strip-components=2 --backup=t --one-top-level=temp
bar/a/e/
bar/a/e/bar
bar/a/f/
bar/a/f/bar
bar/a/c/
bar/a/c/bar
bar/a/d/
bar/a/d/bar
bar/b/e/
bar/b/e/bar
Renaming ‘temp/e/bar’ to ‘temp/e/bar.~1~’
bar/b/f/
bar/b/f/bar
Renaming ‘temp/f/bar’ to ‘temp/f/bar.~1~’
bar/b/c/
bar/b/c/bar
Renaming ‘temp/c/bar’ to ‘temp/c/bar.~1~’
bar/b/d/
bar/b/d/bar
Renaming ‘temp/d/bar’ to ‘temp/d/bar.~1~’
bar/c/e/
bar/c/e/bar
Renaming ‘temp/e/bar’ to ‘temp/e/bar.~2~’
bar/c/f/
bar/c/f/bar
Renaming ‘temp/f/bar’ to ‘temp/f/bar.~2~’
bar/c/c/
bar/c/c/bar
Renaming ‘temp/c/bar’ to ‘temp/c/bar.~2~’
bar/c/d/
bar/c/d/bar
Renaming ‘temp/d/bar’ to ‘temp/d/bar.~2~’

$ tree temp
temp
├── c
│   ├── bar
│   ├── bar.~1~
│   └── bar.~2~
├── d
│   ├── bar
│   ├── bar.~1~
│   └── bar.~2~
├── e
│   ├── bar
│   ├── bar.~1~
│   └── bar.~2~
└── f
    ├── bar
    ├── bar.~1~
    └── bar.~2~

4 directories, 12 files

tar出力を使用すると、tarがバックアップ用にファイルの名前を変更したときを確認でき、どのファイルがどのバックアップになったかを追跡できます。


私はそれが機能することに少し驚いていますが、実際に--one-top-levelに同じディレクトリ名を提供し、名前を変更する必要をなくすことができます。このパイプラインだけで十分です。

tar c --remove-files bar | tar xv --strip-components=2 --backup=t --one-top-level=bar
1
muru