短いファイル名の違いを実行するには?

短いファイル名の違いを実行するには?

私は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

これはdir1sumのすべての名前を繰り返します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表示するか、または存在するが存在しないファイルのみを表示するように指定することもできます。dir2dir1-2dir1dir2

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のいずれかをさらに処理できます。

関連情報