あるプロジェクトが終了して作業していたディレクトリを削除するとき、
  • ファイル
  • ディレクトリ
  • シンボリックリンク
などが含まれる場合、単純に「rm」コマンドで消してしまってシンボリックリンク先のデータまで消してしまわないか不安なので、安全なディレクトリの削除方法について調査した記録

インターネット上には「rmコマンドはシンボリックリンク先まで削除する」だとか、「unlinkコマンドを使えば安全」だとか、「rmとunlinkは内部的に同じである」だとか、真偽の分からない情報が錯綜しているので改めて自分で動かして見て確認する。


削除想定するディレクトリ構造


bbbのディレクトリを例としてシンボリックリンクを含むディレクトリを削除することを考える
├── aaa
│   └── aaa.txt
└── bbb  // 削除対象ディレクトリ
    ├── aaa -> ./aaa
    ├── bbb.txt
    └── ccc
        └── aaa -> ./aaa/aaa.txt
bbbディレクトリ配下には、aaaのディレクトリやファイルに対してシンボリックリンクが配置されている。bbbの削除の際にaaaのディレクトリに影響を与えないようにする。

ディレクトリ構造の作成手順:
mkdir aaa
touch ./aaa/aaa.txt
mkdir bbb
touch ./bbb/bbb.txt
mkdir ./bbb/ccc
ln -s ./aaa ./bbb/aaa
ln -s ./aaa/aaa.txt ./bbb/ccc/aaa
動作確認環境:
・Ubuntu 22.04.4 LTS

安全な削除方法一覧


方法1. rmコマンドを用いる

基本的にrmコマンドで削除するで問題ないようです。シンボリックリンク先を削除するための余計なオプションを付けない限りシンボリックリンク先まで削除することはありません

コマンド:
rm ./bbb -rf
実行後ディレクトリ:(bbb下だけ消える)
├── aaa
│   └── aaa.txt
シンボリックリンク先であった、aaaディレクトリ以下の要素は削除されず残っています。

参考:

本記事末尾にシンボリックリンクを直接指定して削除する場合の補足あり。

方法2. unlinkコマンドを用いる


unlikコマンドは、rmコマンドの「単一ファイルの削除機能」を切り出したもので、ファイル、シンボリックリンクの削除に使えます。(もちろんシンボリックリンク先を再帰的に削除しません)

「単一」ファイルの削除なので、再帰的に削除していかない点でシンボリックリンクの削除向けで安全という通説が広まっているのかもしれません。

つまり、ディレクトリは削除できないのでunlinkを用いる場合はfindコマンドなどを併用します。面倒なのでこちらを無理して使う理由はあまりないような気もします。

以下3ステップで順に削除していきます。

Step1.
コマンド:
# ファイルだけを削除
find ./bbb/ -type f -delete
ディレクトリやシンボリックリンクは削除しないでスルー

Step2.
コマンド:
# シンボリックの削除(シンボリック先まで再帰的に削除しない)
find ./bbb/ -type l | xargs -i unlink {}
or
# シンボリックの削除(シンボリック先まで再帰的に削除しない)
find ./bbb/ -type l | xargs rm

Step3.
コマンド:
# 空になったディレクトリを削除
find /bbb/ -type d -empty -delete

実行後ディレクトリ:(bbb下だけ消える)
├── aaa
│   └── aaa.txt
シンボリックリンク先であった、aaaディレクトリ以下の要素は削除されず残っています。


補足: シンボリックリンクだけを指定して削除する動作確認

同じように「-rf」オプションでシンボリックリンクだけを指定して削除してみます。
この場合でも、特にシンボリックリンク先が削除されることはありませんでした。

コマンド:
rm ./bbb/aaa -rf
実行後ディレクトリ:(aaaへのリンクだけ消える)
├── aaa
│   └── aaa.txt
├── bbb
│   ├── bbb.txt
│   └── ccc
│       └── aaa -> ./aaa/aaa.txt
コマンド:
rm ./bbb/aaa/ -rf
実行後ディレクトリ:(なにも消えない)
├── aaa
│   └── aaa.txt
├── bbb
│   ├── aaa -> ./aaa
│   ├── bbb.txt
│   └── ccc
│       └── aaa -> ./aaa/aaa.txt
コマンド:
rm ./bbb/ccc/aaa -rf
実行後ディレクトリ:(aaa.txtへのリンクだけ消える)
├── aaa
│   └── aaa.txt
├── bbb
│   ├── aaa -> ./aaa
│   ├── bbb.txt
│   └── ccc

以上
このエントリーをはてなブックマークに追加
コメントを閉じる

コメント

コメントフォーム
記事の評価
  • リセット
  • リセット