次のディレクトリ構造があります。名前付きファイルがあるディレクトリを見つけて、特定log.xml
のシンボリックリンクが指すディレクトリを除くすべてのディレクトリを完全に削除する必要があります。
たとえば、/dir1/main/app1/v004/
および/dir1/main/app2/v004/log.xml
シンボリックリンクとして指定されるため、削除しないでください。
また、シンボリックリンクが指すディレクトリ以外のディレクトリを見つけずにどのように削除しますかlog.xml
?
正しいソリューションを提供するのに役立ちますか?
/dir1/main/app1/v001/
/dir1/main/app1/v002/log.xml
/dir1/main/app1/v003/log.xml
/dir1/main/app1/v004/log.xml
/dir1/main/app1/v005/log.xml
/dir1/ln1/app -> /dir1/main/app2/v004
/dir1/main/app2/v001/
/dir1/main/app2/v002/log.xml
/dir1/main/app2/v003/log.xml
/dir1/main/app2/v004/log.xml
/dir1/main/app2/v005/log.xml
/dir1/ln2/app -> /dir1/main/app2/v004
答え1
app
v001
(除外log.xml
)とv004
(シンボリックリンクで指す)を除いて、ディレクトリ内のすべてのサブディレクトリを削除するとします。
for topdir in /dir1 /dir2; do
for dirpath in "$topdir"/main/app/*/; do
if [ -e "$dirpath/log.xml" ] && ! [ "$dirpath" -ef "$topdir"/ln/app ]
then
printf 'Would remove "%s"\n' "$dirpath"
# rm -rf "$dirpath"
fi
done
done
外部ループは、2つの最上位ディレクトリを繰り返すために使用されます/dir1
(これをグローブパターンとして使用/dir2
できます)。/dir[12]
最上位ディレクトリの名前がtopdir
変数に保存されます。
内部ループは以下のサブディレクトリを介して繰り返さapp
れます$topdir
。サブディレクトリに名前付きエントリlog.xml
(最初のテスト、with)が含まれており、シンボリックリンクがそのディレクトリ(2番目のテスト、with)を指し-e
ていない場合は、そのディレクトリを削除できます。"$topdir"/ln/app
-ef
この-e
テストは、指定されたパス名が存在するかどうかの標準テストです。この-ef
テストは非標準ですが、シェルbash
によって実装され、シンボリックリンクを確認した後、両方のパス名が同じファイル(またはこの場合はディレクトリ)を参照するかどうかをテストします。
実際の削除内容は安全のためコメントアウトされています。このコマンドをアクティブにする前に、以前にバックアップしたデータをテストする必要がありますrm
。
という内容が含まれているかどうかにかかわらず、サブディレクトリを削除するには、ステートメントが次のように見えるようにテストを削除しますlog.xml
。-e
if
if ! [ "$dirpath" -ef "$topdir"/ln/app ]; then
printf 'Would remove "%s"\n' "$dirpath"
# rm -rf "$dirpath"
fi
答え2
GNUfind
にはオプションがあります-samefile
。これを機能させるには、-Lオプションを含める必要があります。
次の2つのコマンドの出力を見てください。
(cd /dir1 ; find -L . -samefile ln/app ) # your file and link
(cd /dir1 ; find -L . -not -samefile ln/app ) # everything other than your file and link
2番目は削除したいファイルのリストを生成する必要があります。ディレクトリ以外のファイルだけを一覧表示したい場合があります。その場合は、以下を追加してください。-type f
find -L . -type f -samefile ln/app)
ファイルを削除することは、findコマンドにexecアクションを追加するのと同じくらい簡単です。例えば-exec rm -v {} \;