私はbashシェルを使用しています。両方のディレクトリのファイル名の違いを確認したいのですが、そのディレクトリの直接サブディレクトリのみを確認したいと思います。たとえば、次のサブファイル/ディレクトリがあるディレクトリがあるとします。
dir1
-> abc
-> def
-> ghi
dir2
-> abc
-> fff
-> ghi
dir2には、dir1にはない「fff」という名前のファイル/ディレクトリがあり、「dir1」には、dir2にはない「def」というサブファイル/ディレクトリがあることを示すいくつかのコマンドを実行できるようにしたいです。どうすればいいですか?
答え1
for name in dir1/* dir2/*; do
bname=${name##*/}
if [ ! -e "dir1/$bname" ]; then
printf '"%s" not in dir1\n' "$bname"
elif [ ! -e "dir2/$bname" ]; then
printf '"%s" not in dir2\n' "$bname"
fi
done
これはdir1
sumのすべての名前を繰り返しますdir2
。パスなしで名前$bname
のデフォルト名になります。$name
(デフォルト)名前がで見つからない場合にdir1
報告されます。それ以外の場合、dir2
レポートには見つかりません。
これは、挿入された改行文字を含むファイル名を処理でき、互換性のあるすべての/bin/sh
シェルsh
で実行する必要があります。
これは複数のディレクトリに拡張できます。そしてbash
:
dirs=( dir1 dir2 dir3 dir4 )
for dir in "${dirs[@]}"; do
for name in "$dir"/*; do
bname=${name##*/}
for tdir in "${dirs[@]}"; do
if [ ! -e "$tdir/$bname" ]; then
printf '"%s" not found in %s\n' "$bname" "$tdir"
fi
done
done
done
$ tree
.
|-- dir1
| `-- filename 1
|-- dir2
| |-- filename 1
| |-- filename 3
| `-- hello
world
`-- script.sh
$ sh script.sh
"filename 3" not in dir1
"hello
world" not in dir1
答え2
このために、私はcomm -3
プレーンの出力が本当に好きですls
。
$ comm -3 <(ls dir1) <(ls dir2)
def
fff
最初の列のエントリは最初のディレクトリにのみあり、2番目の列のエントリは2番目のディレクトリにのみあります。この-3
オプションは、両方のディレクトリに共通のエントリを表示する3番目の列を削除します。また、存在するが存在しないファイルのみを-1
表示するか、または存在するが存在しないファイルのみを表示するように指定することもできます。dir2
dir1
-2
dir1
dir2
ls
これを行うには、オプションが設定されていないことを確認する必要があります。渡す対応するOPTIONS
構成またはエイリアスです。次のバリエーションを使用すると、これらの問題を回避できます。
$ comm -z -3 <(cd dir1; printf "%s\0" *) <(cd dir2; printf "%s\0" *) | tr '\0' '\n'
def
fff
後者はファイル名の特殊文字の問題を防ぎます。-1
これをまたは と組み合わせて内部に配置して、2 つの-2
ファイルtr
セットxargs -0
のいずれかをさらに処理できます。