質問をすることでしか得られない、回答やアドバイスがある。

15分調べてもわからないことは、質問しよう!

ただいまの
回答率

89.52%

ディレクトリ内全てのディレクトリ、ファイルを自分自身を含めて削除するシェルスクリプトに関して

解決済

回答 5

投稿 編集

  • 評価
  • クリップ 2
  • VIEW 1,678

sujico.net

score 435

当方、Linuxでシェルスクリプトを書く初心者です。
Webサイトでシェルスクリプトの書き方を確認しながら勉強を進めている状態です。

実現したいこと

以下のようなディレクトリ構成があります。

[/home/xxx/kensyou]
→[/01]
→→[/aaa.html]

→[/02]
→→[/bbb.html]

→[/03]
→→[/ccc.html]

→[/script]
→→[/delete.sh]

【追加検証分】
→[index.php]

この[/home/xxx/kensyou/script/delete.sh]を実行した時、
/home/xxx/kensyou/以下のディレクトリ、ファイルを全て削除したいと考えています。

困っていること

#自身の絶対パスを取得
script_dir_path=$(dirname $(readlink -f $0))

#自身のパスの1つ上 kensyouディレクトリ以下のディレクトリとファイルを全て削除
rm -rf "${script_dir_path}/../*"

kensyouディレクトリ以下の全てを削除することを期待して、
上記のようなスクリプトを書きましたが、削除されたディレクトリ・ファイルはありませんでした。

しかし、「"${script_dir_path}/../*"」の部分をechoで見てみると、
「/home/xxx/kensyou/script/../*」となる為、「rm -rf /home/xxx/kensyou/script/../*」コマンドになりそうなのに
何故削除されないのかが分かりません。

私が何を間違えているのか、
お詳しい方がいらっしゃれば何卒ご教示頂けますと幸いです。

お手数ですが、宜しくお願い致します。

現在の想定

上記スクリプトにより、「rm -rf /home/xxx/kensyou/script/../*」というコマンドが発行されるので、
kensyouディレクトリ以下の全てが削除される筈だと思っていた

追加検証

回答頂いた内容より、
rm -rfのパス指定のクォーテーションを外すことでパスが正しく解釈され、削除が動くようになりました。
しかし、[/home/xxx/kensyou/script/]の直下にファイル(仮にindex.phpなど)がある場合、index.phpの削除がなされないという動作になりました。

script_dir_path=$(dirname $(readlink -f $0))
rm -rf ${script_dir_path}/../*

上記スクリプトのsh -xでの実行結果

+++ readlink -f kensyou/script/delete.sh
++ dirname /home/xxx/kensyou/script/delete.sh
+ script_dir_path=/home/xxx/kensyou/script
+ rm -rf /home/xxx/kensyou/script/../01 /home/xxx/kensyou/script/../02 /home/xxx/kensyou/script/../03 /home/xxx/kensyou/script/../script /home/xxx/kensyou/script/../index.php

echoの内容としては、index.phpも含まれているため、
rm -rfの対象になりそうなのですが、実際にはindex.phpのみ削除がなされないという結果となりました。

推測

index.phpより先にscriptディレクトリの中身が削除されてしまったため、
index.phpの削除処理が走らなかった?(要検証)
→ 回答いただいた方の環境では削除がされたので違う

ファイルのパーミッションの問題?
→ chmod 777でフルアクセスにしてみたが、削除されない

#スクリプト自身の絶対パス取得
script_dir_path=$(dirname $(readlink -f $0))

#ディレクトリ名取得
script_dir=`echo ${script_dir_path} | awk -F "/" '{ print $NF }'`

#最初に自分自身のディレクトリの親ディレクトリから、
#自分自身のディレクトリ以外の配下ディレクトリを削除する
ls ${script_dir_path}/../ | grep -v -E ${script_dir} | xargs rm -rf

#最後に自分自身のディレクトリの親ディレクトリから、
#全ての配下ディレクトリを削除する
rm -rf ${script_dir_path}/../*

上記のような内容で、最初に自分のディレクトリ以外を削除
次に自分を含めて削除とすればどうか検証しましたが、
やはりindex.phpだけが削除されずに残ってしまいました。

また、zzzというディレクトリを作成したところ、index.phpと同様に削除されずに残ってしまうことを確認いたしました。

検証で分かったこと(現状)

scriptディレクトリより後にindex.phpが削除されてしまうため、
「/home/xxx/kensyou/script/../index.php」というパスはありませんよ と怒られてしまっている

scriptだけ最後に消したいが、うまくいかない

  • 気になる質問をクリップする

    クリップした質問は、後からいつでもマイページで確認できます。

    またクリップした質問に回答があった際、通知やメールを受け取ることができます。

    クリップを取り消します

  • 良い質問の評価を上げる

    以下のような質問は評価を上げましょう

    • 質問内容が明確
    • 自分も答えを知りたい
    • 質問者以外のユーザにも役立つ

    評価が高い質問は、TOPページの「注目」タブのフィードに表示されやすくなります。

    質問の評価を上げたことを取り消します

  • 評価を下げられる数の上限に達しました

    評価を下げることができません

    • 1日5回まで評価を下げられます
    • 1日に1ユーザに対して2回まで評価を下げられます

    質問の評価を下げる

    teratailでは下記のような質問を「具体的に困っていることがない質問」、「サイトポリシーに違反する質問」と定義し、推奨していません。

    • プログラミングに関係のない質問
    • やってほしいことだけを記載した丸投げの質問
    • 問題・課題が含まれていない質問
    • 意図的に内容が抹消された質問
    • 過去に投稿した質問と同じ内容の質問
    • 広告と受け取られるような投稿

    評価が下がると、TOPページの「アクティブ」「注目」タブのフィードに表示されにくくなります。

    質問の評価を下げたことを取り消します

    この機能は開放されていません

    評価を下げる条件を満たしてません

    評価を下げる理由を選択してください

    詳細な説明はこちら

    上記に当てはまらず、質問内容が明確になっていない質問には「情報の追加・修正依頼」機能からコメントをしてください。

    質問の評価を下げる機能の利用条件

    この機能を利用するためには、以下の事項を行う必要があります。

回答 5

checkベストアンサー

+2

やってみました。

#!/binsh

#自身の絶対パスを取得
script_dir_path=$(dirname $(readlink -f $0))

#自身のパスの1つ上 kensyouディレクトリ以下のディレクトリとファイルを全て削除
rm -rf ${script_dir_path}/../*

で、うまくいきました。

rm -rf "${script_dir_path}/../*"

だと

rm -rf '/home/xxx/kensyou/script/../*'

と解釈されますね。 ''で囲まれているのでうまく解釈できないようです。

" をはずすとうまくできました。

ちなみに #!/bin/sh (シェバン)の後ろに -x をつけると動きが追えますよ。

投稿

  • 回答の評価を上げる

    以下のような回答は評価を上げましょう

    • 正しい回答
    • わかりやすい回答
    • ためになる回答

    評価が高い回答ほどページの上位に表示されます。

  • 回答の評価を下げる

    下記のような回答は推奨されていません。

    • 間違っている回答
    • 質問の回答になっていない投稿
    • スパムや攻撃的な表現を用いた投稿

    評価を下げる際はその理由を明確に伝え、適切な回答に修正してもらいましょう。

  • 2018/11/20 10:05

    scriptディレクトリより後にindex.phpが削除されてしまうため、
    「/home/xxx/kensyou/script/../index.php」というパスはありませんよ と怒られてしまっていたようです。

    scriptディレクトリだけ最後に削除できたら良かったのですが、
    方法が分からなかったので諦めて削除パスには予め絶対パスを指定するように致しました。

    根本的な解決方法を示して頂きましたので、ベストアンサーとさせて頂きます。
    ご回答頂きありがとうございました。

    キャンセル

  • 2018/11/20 10:33

    最後のところで、具体的な回答を見いだせず、申し訳ないです。

    キャンセル

  • 2018/11/20 10:38

    とんでもございません、基礎から分かっていなかった為大変勉強になりました。
    ありがとうございました。

    キャンセル

+1

script_dir_path=${HOME}

rm -fr "${script_dir_path}/hoge"

script_dir_pathでパス取得がうまくできていないかもしれません。

参考になるかわかりませんが、HOME直下にあるhogeディレクトリを削除するスクリプトです。
解析に役立てば幸いです。

投稿

  • 回答の評価を上げる

    以下のような回答は評価を上げましょう

    • 正しい回答
    • わかりやすい回答
    • ためになる回答

    評価が高い回答ほどページの上位に表示されます。

  • 回答の評価を下げる

    下記のような回答は推奨されていません。

    • 間違っている回答
    • 質問の回答になっていない投稿
    • スパムや攻撃的な表現を用いた投稿

    評価を下げる際はその理由を明確に伝え、適切な回答に修正してもらいましょう。

  • 2018/11/19 17:29

    ご回答頂き、ありがとうございます。
    --
    script_dir_path=$(dirname $(readlink -f $0))
    echo $script_dir_path
    echo "${script_dir_path}/../*"
    --

    という内容でscript_dir_pathの中身を確認してみましたが、
    「/home/xxx/kensyou/script
     /home/xxx/kensyou/script/../*」という結果が返ってきました。

    パスの取得自体は出来ているような気がしますが、
    引き続き検証の参考とさせて頂きます。
    ありがとうございます。

    キャンセル

+1

"${script_dir_path}/../../*" の部分をechoで見てみると、
/home/xxx/kensyou/script/../* となる為、

本当にそうなっていますか?
ファイルパスから考えると、 script_dir_path=/home/xxx/kensyou/script となっているはずなので

rm -rf /home/xxx/kensyou/script/../../*

となっているはずですよ。

投稿

  • 回答の評価を上げる

    以下のような回答は評価を上げましょう

    • 正しい回答
    • わかりやすい回答
    • ためになる回答

    評価が高い回答ほどページの上位に表示されます。

  • 回答の評価を下げる

    下記のような回答は推奨されていません。

    • 間違っている回答
    • 質問の回答になっていない投稿
    • スパムや攻撃的な表現を用いた投稿

    評価を下げる際はその理由を明確に伝え、適切な回答に修正してもらいましょう。

  • 2018/11/19 17:46

    ご回答頂きありがとうございます。
    上記、仰る通りでございます。

    "${script_dir_path}/../../*" に関してですが、
    "${script_dir_path}/../*" のタイプミスでしたので、修正させていただきました。

    ご確認頂きありがとうございます。

    キャンセル

+1

相対パス指定文字列 ../ がLinux(CentOS)上でしたり、シェル上で実際にどの様に解釈されるのかは、私もはっきりとは分からないので省かせていただきます。

手元の業務で使っているMacにインストールしているfish shellで試してみましたが、cd /path/to/dir/../../ と入力すると、確かに /path ディレクトリに移動しますね……(個人的には怖い)

 「ではどうするか」に至る前の考え(長いっす)

cd コマンドでは動くのに、 rm コマンドでは通らない」
ので、
rm コマンドでは、うっかりミスによるファイル消去で、大事なファイルを消さないように作られているのでは?」

と思いまして、 man rm で、コマンドのマニュアルを確認しました。
Man page of RM

しかし、 .. に関する記載は無く、

rm の完全なドキュメントはinfoマニュアルとしてメンテナンスされている。 info と rm が正しくインストールされていれば、次のコマンド
   info rm 
で完全なマニュアルを参照することができる。 

と記されているので、素直に info rm を Macのターミナルで叩いて確認しました。すると、

 Any attempt to remove a file whose last file name component is '.' or
'..' is rejected without any prompting, as mandated by POSIX.

と記されていました。

この文面から察するに、 .. や . といった相対ディレクトリ指定が入っていると、 rm コマンドでは無視をしそうな事が伺えます。

 ではどうするか

消したいファイルの絶対パスを取得できるのであれば、絶対パスで操作を行う様なシェルスクリプトを書いた方が良いです。

もしそれがかなわないのであれば、

  1. 一旦 kensyou ディレクトリそのものごと中身を削除
  2. kensyou ディレクトリを作成

というスクリプトを書いたほうが、気持ち的に安全かなと思います。

以上で、私の回答とさせていただきます。参考になれば幸いです。

投稿

  • 回答の評価を上げる

    以下のような回答は評価を上げましょう

    • 正しい回答
    • わかりやすい回答
    • ためになる回答

    評価が高い回答ほどページの上位に表示されます。

  • 回答の評価を下げる

    下記のような回答は推奨されていません。

    • 間違っている回答
    • 質問の回答になっていない投稿
    • スパムや攻撃的な表現を用いた投稿

    評価を下げる際はその理由を明確に伝え、適切な回答に修正してもらいましょう。

  • 2018/11/19 18:02

    ディレクトリそのものを削除するという方法も確かにありますね。
    ありがとうございます、こちらも参考にさせて頂きたいと思います。

    ご回答頂きありがとうございました。

    キャンセル

+1

scriptディレクトリより後にindex.phpが削除されてしまうため、
「/home/xxx/kensyou/script/../index.php」というパスはありませんよ と怒られてしまっていたようです。

なるほど!
しかし、普通は、*は文字コード順に展開されるはず(index.phpscriptより先)のはずなんですが。

これで行けると思います。

#!/binsh

script_dir_path=$(dirname $(readlink -f $0))
dir_path=$(readlink -f $script_dir_path/..)

rm -rf ${dir_path}/*

投稿

  • 回答の評価を上げる

    以下のような回答は評価を上げましょう

    • 正しい回答
    • わかりやすい回答
    • ためになる回答

    評価が高い回答ほどページの上位に表示されます。

  • 回答の評価を下げる

    下記のような回答は推奨されていません。

    • 間違っている回答
    • 質問の回答になっていない投稿
    • スパムや攻撃的な表現を用いた投稿

    評価を下げる際はその理由を明確に伝え、適切な回答に修正してもらいましょう。

  • 2018/11/20 10:30

    ご回答頂きありがとうございます!
    上記スクリプトですが(先に値を確認しなかった自分が悪いのですが)そのまま実行したら/以下全部消えてしまいました...

    キャンセル

  • 2018/11/20 10:45

    $dir_path が空になっていたと言う事だと思いますが、タイプミスがないとすると、どこをどう間違えればそうなるのか、ちょっとわかりません。

    キャンセル

  • 2018/11/20 10:46

    おっと、他の方の回答からコピーしたので、#!/binsh になってました。#!/bin/sh です。

    キャンセル

15分調べてもわからないことは、teratailで質問しよう!

  • ただいまの回答率 89.52%
  • 質問をまとめることで、思考を整理して素早く解決
  • テンプレート機能で、簡単に質問をまとめられる
  • トップ
  • CentOSに関する質問
  • ディレクトリ内全てのディレクトリ、ファイルを自分自身を含めて削除するシェルスクリプトに関して