*nixワンライナー: 拡張子でファイルを再帰的に検索し、拡張子の名前の新しいディレクトリにコピーします。

*nixワンライナー: 拡張子でファイルを再帰的に検索し、拡張子の名前の新しいディレクトリにコピーします。

さまざまなファイル タイプ (csv、txt、jpg など) を含む多数のディレクトリ/サブディレクトリがある場合、各ディレクトリを再帰的に検索し、各拡張子にちなんで名付けられた新しい最上位ディレクトリにファイルをコピーするコマンドは何ですか。

これをワンライナーで実現する方法はありますか?

答え1

解決

次のコマンドは、現在のディレクトリ ( .) 内のすべてのファイルを一覧表示し、 内の拡張子に基づいて名前が付けられたディレクトリに移動します./OUTPUT

for file in $(find . -type f) ; do EXTENSION=$(echo "$file" |sed 's/.*\.//g') ; rsync -av $file ./OUTPUT/$EXTENSION/ ; done

上記のコマンドを実行する前に、次の操作を行う必要があります。

  • 現在のディレクトリにディレクトリOUTPUTを作成します(mkdir OUTPUT
  • サブディレクトリに一致する名前のファイルがないことを確認します。

説明

まず、ループはfileの出力からのファイルを変数に割り当てますfind . -type f。コマンドの出力例はfind次のとおりです。

./a/myfile1.zip
./a/b/adoc1.txt
./a/b/adoc2.txt
./a/b/adoc3.txt
./a/b/adoc4.txt
./a/myfile3.zip
./a/myfile4.zip
./a/myfile2.zip

変数EXTENSIONが作成され、その値はfile最後のピリオドまでのすべてが削除された変数になります。したがって、./a/myfile1.zipになりますzip

その後、ファイルは、ファイル拡張子に基づいて名付けられたv内のディレクトリに (詳細度付きで)同期されます。OUTPUT

何らかのテストでこのコマンドを実行した後のファイル ツリーの例:

./a
./a/b
./a/b/adoc1.txt
./a/b/adoc2.txt
./a/b/adoc3.txt
./a/b/adoc4.txt
./a/b/c
./a/myfile1.zip
./a/myfile2.zip
./a/myfile3.zip
./a/myfile4.zip
./b
./b/c
./b/c/d
./b/c/file1.txt
./b/c/file2.txt
./b/c/file3.txt
./b/c/file4.txt
./c
./c/d
./c/d/e
./c/d/e/afile1.rar
./c/d/e/afile2.rar
./c/d/e/afile3.rar
./c/d/e/afile4.rar
./OUTPUT
./OUTPUT/rar
./OUTPUT/rar/afile1.rar
./OUTPUT/rar/afile2.rar
./OUTPUT/rar/afile3.rar
./OUTPUT/rar/afile4.rar
./OUTPUT/txt
./OUTPUT/txt/adoc1.txt
./OUTPUT/txt/adoc2.txt
./OUTPUT/txt/adoc3.txt
./OUTPUT/txt/adoc4.txt
./OUTPUT/txt/file1.txt
./OUTPUT/txt/file2.txt
./OUTPUT/txt/file3.txt
./OUTPUT/txt/file4.txt
./OUTPUT/zip
./OUTPUT/zip/myfile1.zip
./OUTPUT/zip/myfile2.zip
./OUTPUT/zip/myfile3.zip
./OUTPUT/zip/myfile4.zip

答え2

これは非常に簡単に行うことができます探すアレックスが正しく示唆したように、ファイルをスキャンするディレクトリが/path1/to/some/dir、ファイルを移動したい場合/path2/to/other/dir/txt等々、

find /path1/some/dir -type f -exec bash -c 'MYDIR=/path2/to/other/dir${0##*.}; [ -d $MYDIR ] && mv $0 $MYDIR  || mv $0 /path3/to/miscellanea' {} \; 

このコマンドはまずすべてのファイルを検索します(-タイプf)ディレクトリ内に含まれる/path1/to/some/dirおよびそのサブディレクトリすべてを検索し、各ファイルの名前を渡します({})を小さなbashの2行コードに置き換えると、まずファイル名から拡張子($0bash内部で)ローカルシェル変数に割り当てますマイディル、 それからテスト適切なディレクトリが存在するかどうか(そのようなディレクトリが存在しない場合は、おそらく間違いを犯した可能性があります)、およびディレクトリが存在するかどうか(&& ...)適切なディレクトリにファイルを移動します。そうでない場合は(...)ファイルをデフォルトの場所に配置し、/path3/to/miscellanea

上記は、必要なディレクトリがすでに作成されていることを前提としています。/path2/to/other/dir/txtなどです。代わりに、外出先で作成したい場合は、上記を次のように変更する必要があります。

find /path1/some/dir -type f -exec bash -c 'MYDIR=/path2/to/other/dir/${0##*.}; mkdir -p $MYDIR && mv $0 $MYDIR' {} \; 

関連情報