フォルダ構造の平坦化


8

私はこのフォルダー構造を持っています:

├── foo1
   ├── bar1.txt
   └── bar2.txt
├── foo2
   ├── bar3.txt
   └── bar4 with a space.txt
└── foo3
    └── qux1
        ├── bar5.txt
        └── bar6.txt

各フォルダーレベルの間にアンダースコアを付けて、これにフラット化したいと思います。

├── foo1_bar1.txt
├── foo1_bar2.txt
├── foo2_bar3.txt
├── foo2_bar4 with a space.txt
├── foo3_qux1.bar6.txt
└── foo3_qux1_bar5.txt

調べてみましたが、うまくいく解決策が見つかりませんでした。ほとんどの場合、私の問題には2つの特殊性があるためだと思います。ルートレベル内に複数のフォルダーレベルがある場合と、一部のファイルにスペースがある場合があります。

これをbashで達成する方法はありますか?ありがとう!

編集:グリーンジャックマンの提案された回答の実行私はこれを取得します。

ここに画像の説明を入力してください

第1レベルのフォルダーには2つの下線があります。これを回避する方法、または名前を1つだけアンダースコアに変更する方法はありますか?ありがとう。

回答:


15
find */ -type f -exec bash -c 'file=${1#./}; echo mv "$file" "${file//\//_}"' _ '{}' \;

echo満足している場合は削除してください。エコーされたコマンドが引用符を表示しないことを心配しないでください。スクリプトはスペースを含むファイルを適切に処理します。

空になったサブディレクトリを削除する場合:

find */ -depth -type d -exec echo rmdir '{}' \; 

ねえ。すごい!ありがとう。それはほとんど完全にトリックをしました。マイナーな問題が発生していfoo1__qux1_bar5.txtます。つまり、最初のフォルダーレベルに2つのアンダースコアが表示されます。bashの行をいじってみましたが、何も機能しないようです。多分私は何かを追加する必要がありますか?
nunos

@nunos、私はその振る舞いを再現することはできません
グレン

本当に?変だ。私はちょうどいくつかの詳細で私の答えを更新しました。見ていただけますか?ありがとう。
nunos

1
ええと。では、に変更"${file//\//_}"します"${file//+(/)/_。これがスクリプトの場合、shopt -s extglob
glenn jackman

2つのアンダースコアにも問題がありました。残念ながら、あなたが提案したようにコマンドを変更してもうまくいきませんでした。私はAskDifferentでこの答えを見つけました:apple.stackexchange.com/a/254224/122152 答えによると、macOSはBSD findを使用している可能性があります。回避策は、findutilsを使用することです。でを使用してインストールしbrew install findutils、のgfind代わりにを使用してインストールできますfind。これでうまくいきました。
インタグリ2018

5

perlの名前変更を使用する:

find . -depth -type f -exec rename 's@(?<!\.)/@_@g' -- {} \;

出力

$ find -type f
./foo2_bar4 whit a space.txt
./foo3_qux1_bar6.txt
./foo2_bar3.txt
./foo3_qux1_bar5.txt
./foo1_bar2.txt
./foo1_bar1.txt

注意

警告 同じ名前のツールが他にもある場合がありますので、ご注意ください。

次のコマンドを実行すると(GNU

$ file "$(readlink -f "$(type -p rename)")"

そしてあなたは次のような結果を持っています

.../rename: Perl script, ASCII text executable

含まない:

ELF

次に、これは適切なツールのようです=)

そうでない場合は、それをデフォルト(通常はすでにそうである)にしDebian、次のような派生物にするUbuntu

$ sudo update-alternatives --set rename /path/to/rename

(コマンド/path/to/renameのパスに置き換えますperl's rename


このコマンドがない場合は、パッケージマネージャーを検索してインストールするか、手動で実行してください


最後に重要なことですが、このツールはもともとPerlの父親であるLarry Wallによって書かれました。


... -type d -exec rmdir ...?
JJoao 2015年

名前を変更できないようです。どのようにして正確に取得できますか?これは通常UNIXシステムで利用できますか?ありがとう。
nunos

@nunos Perlスクリプトです。perl-renameArch LinuxやprenameDebianベースのシステムでは、その名前で利用できます。
muru

rename説明を追加
Gilles Quenot

1

pax...

pax -Xrwls '|/|_|g' */ "$PWD"

これにより、現在のディレクトリに、子ディレクトリのすべてのファイルへのハードリンクが作成さ_/ます。次に、結果を調べて、すべての子ディレクトリを削除できます...

rm -rf */

...結果が自分の好みに合っていることを確認したら、


0

以下のコマンドで試すことができます。

$ find -type f -exec bash -c 'mv $0 $(echo $0|sed "s/\//_/2")' {} \;

上記のコマンドはファイルを移動し、ディレクトリは残りますが、後で削除できます。

$ ls
foo1_bar1.txt  foo1_bar2.txt  foo2_bar3.txt  foo2_bar4.txt  foo3_bar5.txt  foo3_bar6.txt
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.