web-dev-qa-db-ja.com

フォルダ構造の平坦化

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

├── 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で達成する方法はありますか?ありがとう!

編集:グリーンジャックマンを実行すると、答えが得られます。

enter image description here

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

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

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

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

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

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

注意

  • 私は ネガティブルックビハインド(?<!\.)を使用して、最初の./に触れないようにします
  • 私は空のディレクトリを保持します。お気軽に:

    find . -depth -type d -exec rm {} \;

warningこれを実行できる場合とできない場合がある同じ名前のツールが他にもあるため、注意してください。

次のコマンドを実行すると(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/renamePerl's renameコマンドのパスに置き換えます。


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


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

5
Gilles Quenot

pax ...

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

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

rm -rf */

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

1
mikeserv

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

$ 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
0
Kannan Mohan