
テスト環境:
0
からまでのディレクトリを作成し、 からまでの9
ファイルで埋めます。a
z
$ mkdir {0..9} && touch {0..9}/{a..z}
- の結果
find
:$ find -type f ./0/a ./0/b ... ./9/y ./9/z
出力を次のように変換するにはどうすればよいでしょうか。
./0a
./0b
...
./9y
./9z
答え1
Perl のスタンドアロンrename
コマンドを使用する場合:
rename -n 's|/||' */*
すべて問題がなければ、削除して-n
から残りの空のディレクトリを削除します。
rmdir {0..9}
答え2
POSIXツールでは、
find . -type f -exec sh -c 'for f; do dirn="${f%/*}"; mv -- "$f" "$dirn${f##*/}"; done' sh {} +
find
シェルを起動し、各ファイルに対して for ループを実行します。
dirn="${f%/*}"
ファイル名の最後のスラッシュ以降のすべてを除外して親ディレクトリ名を取得します。${f##*/}
ファイル名の最後のスラッシュより前にあるもの (最後のスラッシュを含む) をすべて除外して、パスなしのファイル名を取得します。
これら2つのシェル構造は、dirname
そしてbasename
なので、このコマンドの同等の形式は次のようになります。
find . -type f -exec sh -c 'for f; do mv -- "$f" "$(dirname "$f")$(basename "$f")"; done' sh {} +
ただし、ファイルごとに 2 つの追加プロセスを生成する必要があるため、この方法は遅くなります。
例に示すように、複数のディレクトリに降りる必要がない場合は、単純なシェル ループでそれを実行します。
for f in */*; do dirn="${f%/*}"; echo mv -- "$f" "$dirn${f##*/}"; done