再帰的なファイルコピーから特定の拡張子を除外するにはどうすればよいですか?

再帰的なファイルコピーから特定の拡張子を除外するにはどうすればよいですか?

*.data という名前のデータ ファイルを除くすべてのファイルとサブディレクトリを宛先ディレクトリにコピーします。

 [ichen@ui01 sub_test]$ ls
a.cxx  a.data  subdir
[ichen@ui01 sub_test]$ ls subdir/
sub_a.cxx  sub_a.data

ご覧のとおり、外部ディレクトリとサブディレクトリにそれぞれ 2 つのデータ ファイルがあります。次のコマンドを使用しました。

[ichen@ui01 sub_test]$ cp -r !(*.data) ../destination_dir/

*.data を除くすべてのファイルを宛先にコピーすることを目指しましたが、サブディレクトリでは機能しません。

  [ichen@ui01 destination_dir]$ ls
a.cxx  subdir
[ichen@ui01 destination_dir]$ ls subdir/
sub_a.cxx  sub_a.data

上記では、このコマンドが最初のディレクトリでのみ機能することがわかりますが、これをすべてのサブディレクトリで機能させるにはどうすればよいですか?

答え1

質問では、コピーでディレクトリ構造を保持することが必須なのか、それともファイルのコピーだけが必要なのかが指定されていません。 *.data という名前ではないすべてのファイルを単純にコピーするには、次のようにします。

find . -type f ! -name '*.data' | xargs cp -t ../destination_dir/

一方、ディレクトリ構造を保持したい場合は、次のようなものを使用できます。

for file in `find . ! -name '*.txt' | sed 's/^.\///'`; do if [ -d "./$file" ]; then mkdir -p "../destination_dir/$file"; else cp "./$file" "../destination_dir/$file"; fi; done

これを行うより簡単な方法があるかどうかはわかりませんが、このコマンドは次のことを実行します。

現在のディレクトリまたはそのサブフォルダ内で *.data に一致しないすべてのファイルとフォルダを検索し、それぞれに対して次の操作を実行します。

ファイルがディレクトリであるかどうかをテストし、ディレクトリである場合は宛先ディレクトリの下に一致するディレクトリを作成し、ファイルである場合は宛先にコピーします。

編集: シェルスクリプトバージョンを追加:

#!/bin/bash

# Disable shell glob expansion within the script
# Required to stop bash from expndinging the glob in $1
set -f

for file in `find . ! -name $1 | sed 's/^.\///'`
  do if [ -d "./$file" ]; then
    mkdir -p "$2/$file"
  else
    cp "./$file" "$2/$file"
fi
done

関連情報