ファイルを1つ上のレベルに移動し、ファイル名の前にフォルダ名を追加しますか?

ファイルを1つ上のレベルに移動し、ファイル名の前にフォルダ名を追加しますか?

テスト環境:

  • ~ からディレクトリを作成し、 ~0から ~ までの9ファイルで埋めます。az
    $ 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

関連情報