2つのファイルディレクトリをパラメータとして使用するbashスクリプトを作成しようとしています。次に、最初のディレクトリのすべてのファイルを繰り返して、2番目のディレクトリにそのファイルがあることを確認します。同じデフォルト名を持つファイルが存在しない場合、ファイルは削除されます。今これが私が持っているものですが、どんな理由であるかすべて一致すると思うので何もしなくなります。
echo "$directory1"
echo "$directory2"
for f1 in "$directory1/*"
do
echo $f1
match=no
for f2 in "$directory2/*"
do
echo $f2
name1="$(basename "$f1")"
name2="$(basename "$f2")"
if [ "$name1" == "$name2" ]
then
match=yes
break
fi
done
echo "$match"
if [[ "$match" == no ]]
then
rm "$f2"
fi
done
答え1
以下は、findを使用して各ディレクトリとベース名のファイルを一覧表示し、並べ替えて並べ替える方法です。次に、各リストをcommに入力し、2番目のディレクトリではなく最初のディレクトリにあるファイルのみを印刷します。リストが期待どおりに表示されたら、rmにパイプできます。
comm -2 -3 <(find "$directory1" -maxdepth 1 -type f | xargs -n1 -d\\n basename | sort) <(find "$directory2" -maxdepth 1 -type f | xargs -n1 -d\\n basename | sort) | xargs -d\\n printf "$directory1/%s\n" | xargs -d\\n rm
注:@LeviUzodikeが指摘したように、2番目のディレクトリにはない最初のディレクトリのファイルを削除しようとしているので、適切に変更しました。また、デフォルト名に-aパラメーターを使用しません。
答え2
元のソリューションを修正するには:
- @Kusalanandaが言ったように、
"$directory1/*"
このandを別々"$directory2/*"
にsumに置き換える必要があります。それ以外の場合、forループは文字通り「」というファイルを見つけようとします。"$directory1"/*
"$directory2"/*
*
- あなたの目標を正しく理解したら、その行は続く
rm "$f2"
必要がありますrm "$f1"
。それ以外の場合、プログラムは一致$directory2
しない最後のファイルを$f1
削除します。$f1
$directory2
これら2つの修正のみを適用すると、スクリプトが機能します(directory1
およびにdirectory2
正しい値が割り当てられていると仮定)。
しかし、@Kusalanandaが言ったように、別のループを実行する必要はありません。 @Kusalanandaが次のようなことを提案したと思います(echo
sを削除し、すでに述べたエラーを修正してください)。
for f1 in "$directory1"/*
do
# ls "$directory2"/$(basename "$f1") &>/dev/null
# if [[ $? != 0 ]]
# EDIT below from @Kusalananda
if [[ -e "$directory2/$(basename "$f1")" ]]
then
rm "$f1"
fi
done
技術的にはこれは別のforループですが(なぜならforループが後ろで行われていると信じているからですls
)、はるかにきれいに見えます。追加の見積もりがありましたら申し訳ありません。私はそれらを使用する方法を最もよく知りません。
答え3
zsh
配列減算演算子を使用する方が簡単です${array1:|array2}
。
#! /bin/zsh -
dir1=${1:?} dir2=${2:?}
dir1_files=(${dir1%/}/*(DN:t))
dir2_files=(${dir2%/}/*(DN:t))
only_in_dir2=(${dir2:|dir1})
(($#only_in_dir2 == 0)) ||
rm -rf -- $dir2/$^only_in_dir2
GNUユーティリティを使用すると、同等のbash
操作が次のように表示されることがあります。
#! /bin/bash -
dir1=${1:?} dir2=${2:?}
export LC_ALL=C
chdir() {
case $1 in
(/*) CDPATH= cd -P "$1";;
("") echo >&2 invalid empty directory; false;;
(*) CDPATH= cd -P "./$1";;
esac
}
list_files() (
shopt -s nullglob dotglob # equivalent of zsh's ND
chdir "$1" &&
set -- * &&
(($# > 0)) &&
printf '%s\0' "$@"
)
comm -z13 <(list_files "$dir1") <(list_files "$dir2") |
(chdir "$dir2" && xargs -r0 rm -rf --)
はい、信じていない、またはこのchdir
機能はPOSIXシェルのディレクトリに変更する方法ですPOSIXは、次の標準改訂版で何をお勧めしますか?。
このzsh
場合、そのファイルを読み取れない場合は、dir1
その中のすべてのファイルが削除されることに注意してください。dir2
一つを使うと読めないとbash
こうなるdir1
または検索できません。cd
(必要に応じて探す許可する)。
一致するファイルのリストの作成中にエラーが発生したときに問題を解決するには、次のようにします。
#! /bin/zsh -
dir1=${1:?} dir2=${2:?}
zmodload zsh/system || exit
ERRNO=0
dir1_files=(${dir1%/}/*(DN:t))
dir2_files=(${dir2%/}/*(DN:t))
if ((ERRNO)); then
syserror -p "An error occurred when trying to read the directories: "
exit 1
fi
only_in_dir2=(${dir2:|dir1})
(($#only_in_dir2 == 0)) ||
rm -rf -- $dir2/$^only_in_dir2