あるディレクトリではファイルを見つけることができますが、別のディレクトリでは見つからないツールはありますか? [コピー]

あるディレクトリではファイルを見つけることができますが、別のディレクトリでは見つからないツールはありますか? [コピー]

あるディレクトリではこれらのファイルを見つけ、他のディレクトリでは見つからないbashスクリプトを作成したいと思います。

以下のスクリプトは機能しますか?そうでないときは?

for i in "$1"/*; do
    f=$(basename $i);
    if [ ! -e "$2"/"$f" ]
    then
        echo $f
    fi
done

diff 2つのディレクトリの内容の違いを見つけることも可能だと聞きました。同じ作業も解決できますか?

それとも別のツールですか?

ありがとうございます。

答え1

はい、この目的に使用できますdiff。とても簡単です:

diff -rq dir1 dir2

この-rオプションはdiffまた、サブディレクトリに再帰するように指示します。この-qオプションは、diffファイルが異なる場合にのみ報告するように指示します。

dir1私は一般的に、どのファイルが存在し、存在しないか、またはその逆のファイルを探したいときにdir2これら2つのオプションを使用します。 (-rサブディレクトリに再帰的に移動したくない場合は、このパラメータを削除することもできますが、両方のディレクトリの直接的な内容のみを考慮してください。)

dir1ここには存在するが存在しないファイルdir2と、存在するが存在しないdir2ファイルが表示されますdir1。たとえば、次のようになります。

$ diff -rq /tmp/dir1/ /tmp/dir2/
Only in /tmp/dir1/: file1
Only in /tmp/dir2/: file2
Only in /tmp/dir2/: file3

指示の 1 つだけが必要で (例:dir1には存在しないファイルdir2)、ファイル名のリストのみを取得する場合 ("only in..." 混乱なし)、もちろん、などをdiff使用して出力をマッサージしてみることができます。grepただし、この場合は最初に使用しないで、sedStéphane Chazelasのソリューションを使用することをお勧めします。awkdiff

答え2

ファイル名に改行文字が含まれていない場合は、次のことができます。

(export LC_ALL=C; comm -23 <(ls -A dir1) <(ls -A dir2))

dir1で見つからないファイルを見つけてくださいdir2

任意のファイル名の場合は、配列減算機能を使用できますzsh

dir1_files=(dir1/*(DN:t)) dir2_files=(dir2/*(DN:t))
dir1_and_not_dir2_files=(${dir1_files:|dir2_files})

(再帰的なファイルリスト*に変更されました)**/*

または、bash4.4+および最新バージョンのGNUユーティリティを使用してください。

readarray -td '' dir1_and_not_dir2_files < <(
  export LC_ALL=C
  shopt -s nullglob  dotglob
  comm -z23 <(printf '%s\0' dir1/* | cut -zd/ -f2-) \
            <(printf '%s\0' dir2/* | cut -zd/ -f2-)
)

(オプションを使用して再帰リストにglobstar置き換えます)***

LC_ALL=Cこれは少なくとも2つの理由で必要です。

  • ファイル名には、すべてのバイトシーケンス(0または(ASCIIベースのシステムでは0x2F)値を除く)を/含めることができます。commテキストユーティリティなので、有効な文字形式を指定しないバイトシーケンスに対しては、未指定の動作が発生します。すべての文字が単一バイトで、すべてのバイトが有効な文字(定義されていない可能性がある)のCロケールでは、spすべてのファイル名は有効なテキストです(また、最大ファイル名の長さが通常最大テキスト行の長さよりもかなり小さいことを考慮してください。 )。 。

  • またcomm、ソートされた入力が必要ですが、一部のロケールでは、一部の文字が未定義のソート順序を持つか、他の文字と同じようにソートされて混乱を引き起こす可能性がありますcomm。たとえば、en_GB.UTF-8ロケールを持つGNUシステムでは、次のようになります。

      $ ls dir1 dir2
      dir1:
      

関連情報