web-dev-qa-db-ja.com

特定の名前のフォルダを除いて、フォルダ内のすべてのフォルダを削除します

毎日のスクリプトを使用して、フォルダー内のすべてのフォルダーを削除する必要があります。その日のフォルダを残す必要があります。

フォルダー 'myfolder'には3つのサブフォルダーがあります: 'test1'、 'test2'および 'test3' 'test2'以外のすべてを削除する必要があります。

私はここで正確な名前を照合しようとしています:

find /home/myfolder -type d ! -name 'test2' | xargs rm -rf

OR

find /home/myfolder -type d ! -name 'test2' -delete

このコマンドは常にメインフォルダー「myfolder」も削除しようとします!これを回避する方法はありますか?

19
Riju Mahna

これにより、_./myfolder_とその内容がすべて保持されることを除いて、_./myfolder/test2_内のすべてのフォルダーが削除されます。

_find ./myfolder -mindepth 1 ! -regex '^./myfolder/test2\(/.*\)?' -delete
_

使い方

  • findは検索コマンドを開始します。
  • _./myfolder_は、ディレクトリ_./myfolder_とその内容から開始するようにfindに指示します。

  • _-mindepth 1_ _./myfolder_自体とは一致せず、その下のファイルとディレクトリのみ。

  • ! -regex '^./myfolder/test2\(/.*\)?'は、正規表現^./myfolder/test2\(/.*\)?に一致するファイルまたはディレクトリを除外するように(_!_)指示します。 _^_は、パス名の先頭と一致します。式_(/.*\)?_は、(a)スラッシュの後に何かが続くか、(b)何も一致しないかのいずれかに一致します。

  • _-delete_は、一致する(つまり、除外されない)ファイルを削除するようにfindに指示します。

次のようなディレクトリ構造を考えてみてください。

_$ find ./myfolder
./myfolder
./myfolder/test1
./myfolder/test1/dir1
./myfolder/test1/dir1/test2
./myfolder/test1/dir1/test2/file4
./myfolder/test1/file1
./myfolder/test3
./myfolder/test3/file3
./myfolder/test2
./myfolder/test2/file2
./myfolder/test2/dir2
_

Findコマンド(_-delete_なし)を実行して、一致するものを確認できます。

_$ find ./myfolder -mindepth 1 ! -regex '^./myfolder/test2\(/.*\)?'
./myfolder/test1
./myfolder/test1/dir1
./myfolder/test1/dir1/test2
./myfolder/test1/dir1/test2/file4
./myfolder/test1/file1
./myfolder/test3
./myfolder/test3/file3
_

残っているファイルを調べることで、これが機能したことを確認できます。

_$ find ./myfolder
./myfolder
./myfolder/test2
./myfolder/test2/file2
./myfolder/test2/dir2
_
33
John1024

bashを使用

shopt -s extglob
rm -r myfolder/!(test2)/

例:

$ tree myfolder/
myfolder/
├── test1
│   └── file1
├── test2
│   └── file2
└── test3
    └── file3

$ echo rm -r myfolder/!(test2)
rm -r myfolder/test1 myfolder/test3
$ rm -r myfolder/!(test2)
$ tree myfolder/
myfolder/
└── test2
    └── file2

1 directory, 1 file
10
Jeff Schaller

tl; dr

find ./myfolder -mindepth 1 -maxdepth 1 -type d -not -name test2 \
     -exec echo rm -rf '{}' \;

ファイルのリストに満足したら、エコーを削除します。


-mindepth 1を使用すると、topディレクトリが選択されていないことを確認できます。

$ find ./myfolder -mindepth 1 -type d
./myfolder/test2
./myfolder/test2/one
./myfolder/test2/two
./myfolder/test
./myfolder/test/a1
./myfolder/test/a1/a2
./myfolder/test/a1/a2/a3

しかし、-not -name test2nottest2内のサブディレクトリを回避します。

$ find ./myfolder -mindepth 1 -type d -not -name 'test2'
./myfolder/test2/one
./myfolder/test2/two
./myfolder/test
./myfolder/test/a1
./myfolder/test/a1/a2
./myfolder/test/a1/a2/a3

そのためには、Pruneのようなものが必要です。

$ find ./myfolder -mindepth 1 -name test2 -Prune -o -type d -print
./myfolder/test
./myfolder/test/a1
./myfolder/test/a1/a2
./myfolder/test/a1/a2/a3

Butdeleteを意味するため、depthを使用しないでください。これにより、最長パスから消去が開始されます。

$ find ./myfolder -depth -mindepth 1 -name test2 -Prune -o -type d -print
./myfolder/test/a1/a2/a3
./myfolder/test/a1/a2
./myfolder/test/a1
./myfolder/test

rm -rfを使用します(実際に消去する場合は、echoを削除します)。

$ find ./myfolder -mindepth 1 -name test2 -Prune -o -type d -exec echo rm -rf '{}' \;
rm -rf ./myfolder/test
rm -rf ./myfolder/test/a1
rm -rf ./myfolder/test/a1/a2
rm -rf ./myfolder/test/a1/a2/a3

または、ディレクトリ(およびその中のすべてのもの)を削除するだけの場合はmaxdepthを使用します(echoを削除して実際に消去します):

$ find ./myfolder -mindepth 1 -maxdepth 1 -type d -not -name test2 -exec echo rm -rf '{}' \;
rm -rf ./myfolder/test

ディレクトリが空でない場合でも、-deleteは失敗します。

$ find ./myfolder -mindepth 1 -maxdepth 1 -type d -not -name test2 -delete
find: cannot delete ‘./myfolder/test’: Directory not empty
5
Isaac

Zshを使用している場合は、次のことができます。

setopt extended_glob # if you don't have it enabled

rm -rf myfolder/^test2
2
JoL

以下のコマンドでテストし、それはうまくいきました

find  /home/myfolder -maxdepth 1 -type d ! -iname test2 -exec rm -rvf {} \;
0