ノート

ノート

ファイルを含むいくつかのサブディレクトリがあるディレクトリがあります。非常に似たサブディレクトリを持つ別のディレクトリがありますが、一部のサブディレクトリが追加または削除された可能性があります。 2つのディレクトリが同じ構造を持つようにサブディレクトリを追加および削除できますか?

コマンドやツールを使ってこれを行う簡単な方法はありますか?それとも、各サブディレクトリを検索し、一致するサブディレクトリがあるかどうかを確認するなど、より複雑なタスクを実行する必要がありますか?

答え1

この回答には、次のツールを使用しました。

  • 吹く
  • comm
  • find
  • xargs

NULで区切られたレコードを処理できるため、最後の3つのユーティリティのGNUバージョンを使用することをお勧めします。

まず、いくつかの変数を宣言します。ディレクトリは複数回変更されるため、これらの変数すべてに絶対パス名を使用する必要があります。

# The directories that will be compared
original_dir='/path/to/original/directory'
copy_dir='/path/to/copy/directory'

# Text files where we will save the structure of both directories
original_structure="${HOME}/original_structure.txt"
copy_structure="${HOME}/copy_structure.txt"

# Text files where we will separate each subdirectory
# depending on the action we will perform on them
dirs_to_add="${HOME}/dirs_to_add.txt"
dirs_to_remove="${HOME}/dirs_to_remove.txt"

両方のディレクトリの現在の構造を保存します。

cd -- "${original_dir}"
find . \! -name '.' -type 'd' -print0 | sort -z > "${original_structure}"

cd -- "${copy_dir}"
find . \! -name '.' -type 'd' -print0 | sort -z > "${copy_structure}"

2つの構造の違いを保存します。

comm -23 -z -- "${original_structure}" "${copy_structure}" > "${dirs_to_add}"
comm -13 -z -- "${original_structure}" "${copy_structure}" > "${dirs_to_remove}"

欠落しているディレクトリを作成します。

cd -- "${copy_dir}"
xargs -0 mkdir -p -- < "${dirs_to_add}"

不要なディレクトリを削除します。

cd -- "${copy_dir}"
xargs -0 rm -rf -- < "${dirs_to_remove}"

一時情報を保持するために作成したテキストファイルを削除します。

rm -- "${original_structure}" "${copy_structure}"
rm -- "${dirs_to_add}" "${dirs_to_remove}"

ノート

  • このメソッドは構造のみをコピーします。所有者、権限、または属性は保持されません。たとえば、他のツールを使用すると保存できるという内容を読んでいrsyncますが、試したことはありません。

  • 上記のコードをスクリプトに入れるには、エラー処理を実装する必要があります。たとえば、cdディレクトリの入力が失敗し、誤ったディレクトリで動作すると、災害の結果につながる可能性があります。

答え2

このようなシェル関数は次のことができます。

comparedirs() (
    cd -- "${1?}";
    for d in */; do
        ! [ -d ../"${2?}"/"$d" ] && printf "%s\n" "$d is in '$1' but not in '$2'"
    done
)

テスト:

$ mkdir -p left/{a,b,c}
$ mkdir -p right/{a,c,d}
$ comparedirs left right
b/ is in 'left' but not in 'right'
$ comparedirs right left
d/ is in 'right' but not in 'left'

../nameこれはファイルではなくサブディレクトリだけを見て、これらのディレクトリが実際に兄弟であると仮定します。つまり、

関連情報