![あるディレクトリではファイルを見つけることができますが、別のディレクトリでは見つからないツールはありますか? [コピー]](https://linux33.com/image/141709/%E3%81%82%E3%82%8B%E3%83%87%E3%82%A3%E3%83%AC%E3%82%AF%E3%83%88%E3%83%AA%E3%81%A7%E3%81%AF%E3%83%95%E3%82%A1%E3%82%A4%E3%83%AB%E3%82%92%E8%A6%8B%E3%81%A4%E3%81%91%E3%82%8B%E3%81%93%E3%81%A8%E3%81%8C%E3%81%A7%E3%81%8D%E3%81%BE%E3%81%99%E3%81%8C%E3%80%81%E5%88%A5%E3%81%AE%E3%83%87%E3%82%A3%E3%83%AC%E3%82%AF%E3%83%88%E3%83%AA%E3%81%A7%E3%81%AF%E8%A6%8B%E3%81%A4%E3%81%8B%E3%82%89%E3%81%AA%E3%81%84%E3%83%84%E3%83%BC%E3%83%AB%E3%81%AF%E3%81%82%E3%82%8A%E3%81%BE%E3%81%99%E3%81%8B%EF%BC%9F%20%5B%E3%82%B3%E3%83%94%E3%83%BC%5D.png)
あるディレクトリではこれらのファイルを見つけ、他のディレクトリでは見つからない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
ただし、この場合は最初に使用しないで、sed
Stéphane Chazelasのソリューションを使用することをお勧めします。awk
diff
答え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: