
次のフォルダ構造があります。
├── 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でこれを達成する方法を知っていますか?ありがとうございます!
編集する:Glenn Jackmanが提案した答えを実行すると、次のような結果が得られます。
最初のレベルのフォルダには2つのアンダースコアがあります。これを避ける方法や名前を変更して下線で表示する方法を知っていますか?ありがとうございます。
答え1
find */ -type f -exec bash -c 'file=${1#./}; echo mv "$file" "${file//\//_}"' _ '{}' \;
echo
仕事に満足したら削除してください。 echoコマンドが引用符を表示しないことを心配しないでください。スクリプトはスペースを含むファイルを正しく処理します。
現在空のサブディレクトリを削除するには、次の手順を実行します。
find */ -depth -type d -exec echo rmdir '{}' \;
答え2
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 {} \;
これを行うこともできないかもしれない同じ名前の他のツールがあるので注意してください。
次のコマンドを実行すると(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によって書かれました。
答え3
そしてpax
...
pax -Xrwls '|/|_|g' */ "$PWD"
これにより、現在のディレクトリにそのサブディレクトリ内のすべてのファイルへのハードリンクが作成され、次のコマンドを使用して結果を確認し、すべてのサブディレクトリを削除できます_
。/
rm -rf */
...結果が気に入ったことを確認した後。
答え4
次のコマンドを試すことができます。
$ 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