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

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

新規登録して質問してみよう
ただいま回答率
85.48%
CentOS

CentOSは、主にRed Hat Enterprise Linux(RHEL)をベースにした、フリーのソフトウェアオペレーティングシステムです。

sh

shは、UNIX系OSのシェル操作の1つであり、最も基本的なシェルのことです。

Q&A

解決済

5回答

5511閲覧

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

sujico.net

総合スコア453

CentOS

CentOSは、主にRed Hat Enterprise Linux(RHEL)をベースにした、フリーのソフトウェアオペレーティングシステムです。

sh

shは、UNIX系OSのシェル操作の1つであり、最も基本的なシェルのことです。

1グッド

2クリップ

投稿2018/11/19 08:05

編集2018/11/20 00:02

当方、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/以下のディレクトリ、ファイルを全て削除したいと考えています。

##困っていること

sh

1#自身の絶対パスを取得 2script_dir_path=$(dirname $(readlink -f $0)) 3 4#自身のパスの1つ上 kensyouディレクトリ以下のディレクトリとファイルを全て削除 5rm -rf "${script_dir_path}/../*" 6

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の削除がなされないという動作になりました。

sh

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

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

sh

1+++ readlink -f kensyou/script/delete.sh 2++ dirname /home/xxx/kensyou/script/delete.sh 3+ script_dir_path=/home/xxx/kensyou/script 4+ 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でフルアクセスにしてみたが、削除されない

sh

1#スクリプト自身の絶対パス取得 2script_dir_path=$(dirname $(readlink -f $0)) 3 4#ディレクトリ名取得 5script_dir=`echo ${script_dir_path} | awk -F "/" '{ print $NF }'` 6 7#最初に自分自身のディレクトリの親ディレクトリから、 8#自分自身のディレクトリ以外の配下ディレクトリを削除する 9ls ${script_dir_path}/../ | grep -v -E ${script_dir} | xargs rm -rf 10 11#最後に自分自身のディレクトリの親ディレクトリから、 12#全ての配下ディレクトリを削除する 13rm -rf ${script_dir_path}/../*

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

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

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

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

ikedas👍を押しています

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

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

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

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

guest

回答5

0

ベストアンサー

やってみました。

sh

1#!/binsh 2 3#自身の絶対パスを取得 4script_dir_path=$(dirname $(readlink -f $0)) 5 6#自身のパスの1つ上 kensyouディレクトリ以下のディレクトリとファイルを全て削除 7rm -rf ${script_dir_path}/../*

 で、うまくいきました。

sh

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

だと

sh

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

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

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

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

投稿2018/11/19 08:45

showkit

総合スコア1638

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

manzyun

2018/11/19 08:47

質問した方ではありませんが、ものすごく参考になりました。 ありがとうございます!
sujico.net

2018/11/19 09:04 編集

ご確認頂きありがとうございます。 回答を元に試してみたところ、こちらの内容で出来ました! 結合するので文字列として扱わなければならないと思いクォーテーションで囲っていたのですが、それが誤りだったのですね。 -xによる変数確認の方法もご教示頂きありがとうございます。 尚、大変恐縮なのですが、 [/home/xxx/kensyou]の直下にファイル(仮にindex.phpとします)があると、 そのファイルだけ残ってしまうのですが、これは何故だか分かりますでしょうか。 -- script_dir_path=$(dirname $(readlink -f $0)) echo ${script_dir_path}/../* -- 上記の結果では、 /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 と表示されるので、index.phpも削除の対象になっていそうな気はするのですが…。
showkit

2018/11/19 09:22

わはは わたしの回答、1行目が「#!/binsh」になってますね。すみません。おわかりのようですが「#!/bin/sh」の誤りです。 それはともかくとして /home/xxx/kensyou/index.php を置いてやってみましたが。うまく削除できました。謎ですねぇ。 tree で見たり、ls -la で見て 構成やパーミッションに問題がないか確認してみては?
sujico.net

2018/11/19 09:32

なるほど…パーミッションを確認しましたが、 -rw-r--r-- 1 root root 6 11月 19 18:12 2018 index.php とあり、 特に他のファイルと違った様子は見られません。 rm -rfコマンドで直接削除すると、何の警告も無く普通に消えます。 うーん…何故だ 参考にさせて頂きます。ありがとうございます。
sujico.net

2018/11/20 01:05

scriptディレクトリより後にindex.phpが削除されてしまうため、 「/home/xxx/kensyou/script/../index.php」というパスはありませんよ と怒られてしまっていたようです。 scriptディレクトリだけ最後に削除できたら良かったのですが、 方法が分からなかったので諦めて削除パスには予め絶対パスを指定するように致しました。 根本的な解決方法を示して頂きましたので、ベストアンサーとさせて頂きます。 ご回答頂きありがとうございました。
showkit

2018/11/20 01:33

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

2018/11/20 01:38

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

0

scriptディレクトリより後にindex.phpが削除されてしまうため、

「/home/xxx/kensyou/script/../index.php」というパスはありませんよ と怒られてしまっていたようです。

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

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

Bash

1#!/binsh 2 3script_dir_path=$(dirname $(readlink -f $0)) 4dir_path=$(readlink -f $script_dir_path/..) 5 6rm -rf ${dir_path}/*

投稿2018/11/20 01:13

otn

総合スコア84499

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

sujico.net

2018/11/20 01:30

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

2018/11/20 01:45

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

2018/11/20 01:46

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

0

相対パス指定文字列 ../ が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 08:41

manzyun

総合スコア2244

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

sujico.net

2018/11/19 09:02

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

0

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

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

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

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

投稿2018/11/19 08:31

mather

総合スコア6753

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

sujico.net

2018/11/19 08:46

ご回答頂きありがとうございます。 上記、仰る通りでございます。 "${script_dir_path}/../../*" に関してですが、 "${script_dir_path}/../*" のタイプミスでしたので、修正させていただきました。 ご確認頂きありがとうございます。
guest

0

script_dir_path=${HOME} rm -fr "${script_dir_path}/hoge"

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

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

投稿2018/11/19 08:24

oh_rusty_nail

総合スコア319

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

sujico.net

2018/11/19 08: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/../*」という結果が返ってきました。 パスの取得自体は出来ているような気がしますが、 引き続き検証の参考とさせて頂きます。 ありがとうございます。
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

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

ただいまの回答率
85.48%

質問をまとめることで
思考を整理して素早く解決

テンプレート機能で
簡単に質問をまとめる

質問する

関連した質問